void EnterPreprocessorTokenStream(clang::Preprocessor& _pp, const clang::Token *start, size_t len, bool DisableMacroExpansion) { #if (LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR == 8) _pp.EnterTokenStream(start, len, false, DisableMacroExpansion); #else _pp.EnterTokenStream(clang::ArrayRef<clang::Token>{start, len}, DisableMacroExpansion); #endif }
clang::FileID CreateFileIDForMemBuffer(clang::Preprocessor &PP, llvm::MemoryBuffer *Buf, clang::SourceLocation Loc) { #if CLANG_VERSION_MAJOR != 3 || CLANG_VERSION_MINOR > 4 return PP.getSourceManager().createFileID(Buf, clang::SrcMgr::C_User, 0, 0, Loc); #else return PP.getSourceManager().createFileIDForMemBuffer(Buf, clang::SrcMgr::C_User, 0, 0, Loc); #endif }
virtual bool HandleComment(clang::Preprocessor& pp, clang::SourceRange range) override { auto FID = pp.getSourceManager().getMainFileID(); int start = range.getBegin().getRawEncoding(); int end = range.getEnd().getRawEncoding(); int length = end - start; auto bufferStart = pp.getSourceManager().getBuffer(FID)->getBufferStart(); int fileOffset = pp.getSourceManager().getLocForStartOfFile(FID).getRawEncoding(); const char* data = bufferStart + start - fileOffset; string str(data, length); cout << str << endl; return false; }
bool MetricPPCustomer::HandleComment(clang::Preprocessor &PP, clang::SourceRange Loc) { clang::SourceLocation Start = Loc.getBegin(); clang::SourceManager &SM = PP.getSourceManager(); std::string fileName = SM.getFilename( Start ).str(); /* Excude comments that are not: - Not in the main file and - Not in the file we're currently processing and - Are in a file we've already processed comments for */ if(( SM.getFileID( Start ) == SM.getMainFileID() ) || ( fileName == m_commentFile ) || ( m_commentFileList->find( fileName ) == m_commentFileList->end() )) { std::string C(SM.getCharacterData(Start), SM.getCharacterData(Loc.getEnd())); if( m_options.ShouldIncludeFile( fileName )) { MetricUnit* unit = m_topUnit->getSubUnit(fileName, METRIC_UNIT_FILE); unit->increment(METRIC_TYPE_COMMENT_BYTE_COUNT, getFileAndLine( SM, &Start ), C.length()); unit->increment(METRIC_TYPE_COMMENT_COUNT, getFileAndLine( SM, &Start )); } m_commentFile = fileName; m_commentFileList->insert( fileName ); } else { m_commentFile = ""; } return false; }
// Get a "file:line:column" source location string. static std::string getSourceLocationString(clang::Preprocessor &PP, clang::SourceLocation Loc) { if (Loc.isInvalid()) return std::string("(none)"); if (Loc.isFileID()) { clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc); if (PLoc.isInvalid()) { return std::string("(invalid)"); } std::string Str; llvm::raw_string_ostream SS(Str); // The macro expansion and spelling pos is identical for file locs. SS << "\"" << PLoc.getFilename() << ':' << PLoc.getLine() << ':' << PLoc.getColumn() << "\""; std::string Result = SS.str(); // YAML treats backslash as escape, so use forward slashes. std::replace(Result.begin(), Result.end(), '\\', '/'); return Result; } return std::string("(nonfile)"); }
static best_guess tok_type(clang::Preprocessor &pp, const char *macro_name, const clang::Token &t, StringSet *seen) { using namespace clang; tok::TokenKind k = t.getKind(); if(k == tok::identifier) { IdentifierInfo *ii = t.getIdentifierInfo(); if(ii && !seen->count(ii->getNameStart())) return macro_type(pp, ii->getNameStart(), pp.getMacroInfo(ii), seen); return tok_ok; } if (k == tok::l_paren || k == tok::r_paren || k == tok::amp || k == tok::plus || k == tok::star || k == tok::minus || k == tok::tilde || k == tok::slash || k == tok::percent || k == tok::lessless || k == tok::greatergreater || k == tok::caret || k == tok::pipe || k == tok::exclaim || k == tok::kw_int || k == tok::kw_float || k == tok::kw_double || k == tok::kw_long || k == tok::kw_signed || k == tok::kw_unsigned) return tok_ok; return tok_invalid; }
static std::string macro_to_string(const clang::Preprocessor &pp, const clang::MacroInfo *mi) { std::stringstream ss; for(clang::MacroInfo::tokens_iterator j = mi->tokens_begin(); j != mi->tokens_end(); j++) { const clang::Token &t = (*j); ss << pp.getSpelling(t); } return ss.str(); }
RSContext::RSContext(clang::Preprocessor &PP, clang::ASTContext &Ctx, const clang::TargetInfo &Target, PragmaList *Pragmas, unsigned int TargetAPI, std::vector<std::string> *GeneratedFileNames) : mPP(PP), mCtx(Ctx), mTarget(Target), mPragmas(Pragmas), mTargetAPI(TargetAPI), mGeneratedFileNames(GeneratedFileNames), mTargetData(NULL), mLLVMContext(llvm::getGlobalContext()), mLicenseNote(NULL), mRSPackageName("android.renderscript"), version(0), mMangleCtx(Ctx.createMangleContext()) { slangAssert(mGeneratedFileNames && "Must supply GeneratedFileNames"); // For #pragma rs export_type PP.AddPragmaHandler( "rs", RSPragmaHandler::CreatePragmaExportTypeHandler(this)); // For #pragma rs java_package_name PP.AddPragmaHandler( "rs", RSPragmaHandler::CreatePragmaJavaPackageNameHandler(this)); // For #pragma rs set_reflect_license PP.AddPragmaHandler( "rs", RSPragmaHandler::CreatePragmaReflectLicenseHandler(this)); // For #pragma version PP.AddPragmaHandler(RSPragmaHandler::CreatePragmaVersionHandler(this)); // Prepare target data mTargetData = new llvm::TargetData(Target.getTargetDescription()); return; }
virtual bool HandleComment( clang::Preprocessor &pp, clang::SourceRange rng) { clang::SourceManager &sm = pp.getSourceManager(); if( sm.getFilename(rng.getBegin()) == m_inFile) { std::pair<FileID, unsigned int> startLoc = sm.getDecomposedLoc(rng.getBegin()); std::pair<FileID, unsigned int> endLoc = sm.getDecomposedLoc(rng.getEnd()); llvm::StringRef fileData = sm.getBufferData(startLoc.first); std::cout << fileData.substr(startLoc.second, endLoc.second - startLoc.second).str(); std::cout << std::endl; } return false; }
/// Classify the given Clang enumeration to describe how to import it. void EnumInfo::classifyEnum(const clang::EnumDecl *decl, clang::Preprocessor &pp) { // Anonymous enumerations simply get mapped to constants of the // underlying type of the enum, because there is no way to conjure up a // name for the Swift type. if (!decl->hasNameForLinkage()) { kind = EnumKind::Constants; return; } // First, check for attributes that denote the classification if (auto domainAttr = decl->getAttr<clang::NSErrorDomainAttr>()) { kind = EnumKind::Enum; attribute = domainAttr; return; } // Was the enum declared using *_ENUM or *_OPTIONS? // FIXME: Use Clang attributes instead of grovelling the macro expansion loc. auto loc = decl->getLocStart(); if (loc.isMacroID()) { StringRef MacroName = pp.getImmediateMacroName(loc); if (MacroName == "CF_ENUM" || MacroName == "__CF_NAMED_ENUM" || MacroName == "OBJC_ENUM" || MacroName == "SWIFT_ENUM" || MacroName == "SWIFT_ENUM_NAMED") { kind = EnumKind::Enum; return; } if (MacroName == "CF_OPTIONS" || MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS") { kind = EnumKind::Options; return; } } // Hardcode a particular annoying case in the OS X headers. if (decl->getName() == "DYLD_BOOL") { kind = EnumKind::Enum; return; } // Fall back to the 'Unknown' path. kind = EnumKind::Unknown; }
void ClangInternalState::printMacroDefinitions(llvm::raw_ostream& Out, const clang::Preprocessor& PP) { stdstrstream contentsOS; PP.printMacros(contentsOS); Out << "Ordered Alphabetically:\n"; std::vector<std::string> elems; { // Split the string into lines. char delim = '\n'; std::stringstream ss(contentsOS.str()); std::string item; while (std::getline(ss, item, delim)) { elems.push_back(item); } // Sort them alphabetically std::sort(elems.begin(), elems.end()); } for(std::vector<std::string>::iterator I = elems.begin(), E = elems.end(); I != E; ++I) Out << *I << '\n'; Out.flush(); }
void PragmaRecorder::HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducerKind Introducer, clang::Token &FirstToken) { clang::Token &CurrentToken = FirstToken; std::string PragmaName, PragmaValue = ""; // Pragma in ACC should be a name/value pair if (GetPragmaNameFromToken(FirstToken, PragmaName)) { // start parsing the value '(' PragmaValue ')' const clang::Token* NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::l_paren)) PP.LexUnexpandedToken(CurrentToken); else goto end_parsing_pragma_value; NextToken = &PP.LookAhead(0); if (GetPragmaValueFromToken(*NextToken, PragmaValue)) PP.Lex(CurrentToken); else goto end_parsing_pragma_value; if (!NextToken->is(clang::tok::r_paren)) { NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::r_paren)) PP.LexUnexpandedToken(CurrentToken); else goto end_parsing_pragma_value; } // Until now, we ensure that we have a pragma name/value pair mPragmas->push_back(make_pair(PragmaName, PragmaValue)); } end_parsing_pragma_value: // Inform lex to eat the token PP.LexUnexpandedToken(CurrentToken); return; }
void InsertIntoAutoloadingState (Decl* decl, std::string annotation) { assert(annotation != "" && "Empty annotation!"); assert(m_PP); const FileEntry* FE = 0; SourceLocation fileNameLoc; bool isAngled = false; const DirectoryLookup* LookupFrom = 0; const DirectoryLookup* CurDir = 0; FE = m_PP->LookupFile(fileNameLoc, annotation, isAngled, LookupFrom, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, /*suggestedModule*/0, /*SkipCache*/false, /*OpenFile*/ false, /*CacheFail*/ false); assert(FE && "Must have a valid FileEntry"); if (m_Map->find(FE) == m_Map->end()) (*m_Map)[FE] = std::vector<Decl*>(); (*m_Map)[FE].push_back(decl); }
static std::pair<clang::StringLiteral*, clang::StringLiteral *> ExtractLiterals(clang::ParenExpr *PE, const clang::Preprocessor &PP, const char *Keyword, const char (&Error)[N]) { clang::BinaryOperator* BO = llvm::dyn_cast<clang::BinaryOperator>(PE->getSubExpr()); clang::StringLiteral *Val1 = nullptr, *Val2 = nullptr; if (!BO) { PP.getDiagnostics().Report(PE->getExprLoc(), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, "Invalid %0 annotation")) << Keyword; } else { if (!(Val1 = llvm::dyn_cast<clang::StringLiteral>(BO->getLHS()))) PP.getDiagnostics().Report(BO->getLHS()->getExprLoc(), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, Error)); if (!(Val2 = llvm::dyn_cast<clang::StringLiteral>(BO->getRHS()))) PP.getDiagnostics().Report(BO->getRHS()->getExprLoc(), PP.getDiagnostics().getCustomDiagID(clang::DiagnosticsEngine::Error, Error)); } return {Val1, Val2}; }
static clang::SourceLocation GetFromLiteral(clang::Token Tok, clang::StringLiteral *Lit, clang::Preprocessor &PP) { return Lit->getLocationOfByte(PP.getSourceManager().getFileOffset(Tok.getLocation()), PP.getSourceManager(), PP.getLangOpts(), PP.getTargetInfo()); }
void PragmaRecorder::HandlePragma(clang::Preprocessor &PP, clang::PragmaIntroducerKind Introducer, clang::Token &FirstToken) { clang::Token &CurrentToken = FirstToken; std::string PragmaName, PragmaValue = ""; // Pragma in ACC should be a name/value pair if (GetPragmaNameFromToken(FirstToken, PragmaName)) { // start parsing the value '(' PragmaValue ')', if we have one. const clang::Token* NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::l_paren)) PP.LexUnexpandedToken(CurrentToken); else goto end_parsing_pragma_value; NextToken = &PP.LookAhead(0); if (GetPragmaValueFromToken(*NextToken, PragmaValue)) { PP.Lex(CurrentToken); } else { PP.LexUnexpandedToken(CurrentToken); PP.Diag(NextToken->getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "expected value after '#pragma %0('")) << PragmaName; return; } if (!NextToken->is(clang::tok::r_paren)) { NextToken = &PP.LookAhead(0); if (NextToken->is(clang::tok::r_paren)) { PP.LexUnexpandedToken(CurrentToken); } else { PP.LexUnexpandedToken(CurrentToken); PP.Diag(NextToken->getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "missing ')' after '#pragma %0(%1'")) << PragmaName << PragmaValue; return; } } } else { PP.Diag(FirstToken.getLocation(), PP.getDiagnostics().getCustomDiagID( clang::DiagnosticsEngine::Error, "no pragma name or value")); return; } end_parsing_pragma_value: // PragmaValue may be an empty string. mPragmas->push_back(make_pair(PragmaName, PragmaValue)); // Inform lex to eat the token PP.LexUnexpandedToken(CurrentToken); return; }
void InsertIntoAutoloadingState(Decl* decl, Annotations_t FileNames) { assert(m_PP); auto addFile = [this,decl](llvm::StringRef FileName, bool warn) { if (FileName.empty()) return (const FileEntry*)nullptr; const FileEntry* FE = 0; SourceLocation fileNameLoc; // Remember this file wth full path, not "./File.h" (ROOT-8863). bool isAngled = true; const DirectoryLookup* FromDir = 0; const FileEntry* FromFile = 0; const DirectoryLookup* CurDir = 0; bool needCacheUpdate = false; if (FileName.equals(m_PrevFileName.first)) FE = m_PrevFE.first; else if (FileName.equals(m_PrevFileName.second)) FE = m_PrevFE.second; else { FE = m_PP->LookupFile(fileNameLoc, FileName, isAngled, FromDir, FromFile, CurDir, /*SearchPath*/0, /*RelativePath*/ 0, /*suggestedModule*/0, /*IsMapped*/0, /*SkipCache*/ false, /*OpenFile*/ false, /*CacheFail*/ true); needCacheUpdate = true; } if (FE) { auto& Vec = (*m_Map)[FE]; Vec.push_back(decl); if (needCacheUpdate) return FE; else return (const FileEntry*)nullptr; } else if (warn) { // If the top level header is expected to be findable at run-time, // the direct header might not because the include path might be // different enough and only the top-header is guaranteed to be seen // by the user as an interface header to be available on the // run-time include path. cling::errs() << "Error in cling::AutoloadingVisitor::InsertIntoAutoloadingState:\n" " Missing FileEntry for " << FileName << "\n"; if (NamedDecl* ND = dyn_cast<NamedDecl>(decl)) { cling::errs() << " requested to autoload type "; ND->getNameForDiagnostic(cling::errs(), ND->getASTContext().getPrintingPolicy(), true /*qualified*/); cling::errs() << "\n"; } return (const FileEntry*)nullptr; } else { // Case of the direct header that is not a top level header, no // warning in this case (to likely to be a false positive). return (const FileEntry*)nullptr; } }; const FileEntry* cacheUpdate; if ( (cacheUpdate = addFile(FileNames.first,true)) ) { m_PrevFE.first = cacheUpdate; m_PrevFileName.first = FileNames.first; } if ( (cacheUpdate = addFile(FileNames.second,false)) ) { m_PrevFE.second = cacheUpdate; m_PrevFileName.second = FileNames.second; } }
void ClangInternalState::printMacroDefinitions(llvm::raw_ostream& Out, clang::Preprocessor& PP) { PP.printMacros(Out); }
void ParserProxy::EnterTokenStream(clang::Preprocessor& PP) { PP.EnterTokenStream(&(CurrentToken()), 1, true, false); }
/// Classify the given Clang enumeration to describe how to import it. void EnumInfo::classifyEnum(ASTContext &ctx, const clang::EnumDecl *decl, clang::Preprocessor &pp) { assert(decl); clang::PrettyStackTraceDecl trace(decl, clang::SourceLocation(), pp.getSourceManager(), "classifying"); assert(decl->isThisDeclarationADefinition()); // Anonymous enumerations simply get mapped to constants of the // underlying type of the enum, because there is no way to conjure up a // name for the Swift type. if (!decl->hasNameForLinkage()) { kind = EnumKind::Constants; return; } // First, check for attributes that denote the classification if (auto domainAttr = decl->getAttr<clang::NSErrorDomainAttr>()) { kind = EnumKind::Enum; nsErrorDomain = ctx.AllocateCopy(domainAttr->getErrorDomain()->getName()); return; } if (decl->hasAttr<clang::FlagEnumAttr>()) { kind = EnumKind::Options; return; } if (decl->hasAttr<clang::EnumExtensibilityAttr>()) { // FIXME: Distinguish between open and closed enums. kind = EnumKind::Enum; return; } // If API notes have /removed/ a FlagEnum or EnumExtensibility attribute, // then we don't need to check the macros. for (auto *attr : decl->specific_attrs<clang::SwiftVersionedAttr>()) { if (!attr->getVersion().empty()) continue; if (isa<clang::FlagEnumAttr>(attr->getAttrToAdd()) || isa<clang::EnumExtensibilityAttr>(attr->getAttrToAdd())) { kind = EnumKind::Unknown; return; } } // Was the enum declared using *_ENUM or *_OPTIONS? // FIXME: Stop using these once flag_enum and enum_extensibility // have been adopted everywhere, or at least relegate them to Swift 3 mode // only. auto loc = decl->getLocStart(); if (loc.isMacroID()) { StringRef MacroName = pp.getImmediateMacroName(loc); if (MacroName == "CF_ENUM" || MacroName == "__CF_NAMED_ENUM" || MacroName == "OBJC_ENUM" || MacroName == "SWIFT_ENUM" || MacroName == "SWIFT_ENUM_NAMED") { kind = EnumKind::Enum; return; } if (MacroName == "CF_OPTIONS" || MacroName == "OBJC_OPTIONS" || MacroName == "SWIFT_OPTIONS") { kind = EnumKind::Options; return; } } // Hardcode a particular annoying case in the OS X headers. if (decl->getName() == "DYLD_BOOL") { kind = EnumKind::Enum; return; } // Fall back to the 'Unknown' path. kind = EnumKind::Unknown; }