// 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)"); }
void NamedDeclMatcher::renameLocation(clang::SourceLocation L, std::string& N) { if (L.isValid()) { if (L.isMacroID()) { // TODO: emit error using diagnostics clang::SourceManager &SM = ci->getSourceManager(); if (SM.isMacroArgExpansion(L) || SM.isInSystemMacro(L)) { // see if it's the macro expansion we can handle // e.g. // #define call(x) x // call(y()); // if we want to rename y() L = SM.getSpellingLoc(L); // this falls through to the rename routine below } else { // if the spelling location is from an actual file that we can // touch, then do the replacement, but show a warning clang::SourceManager &SM = ci->getSourceManager(); auto SL = SM.getSpellingLoc(L); clang::FullSourceLoc FSL(SL, SM); const clang::FileEntry *FE = SM.getFileEntryForID(FSL.getFileID()); if (FE) { llvm::errs() << "Warning: Rename attempted as a result of macro " << "expansion may break things, at: " << loc(L) << "\n"; L = SL; // this falls through to the rename routine below } else { // cannot handle this case llvm::errs() << "Error: Token is resulted from macro expansion" " and is therefore not renamed, at: " << loc(L) << "\n"; return; } } } if (!canChangeLocation(L)) { return; } clang::Preprocessor &P = ci->getPreprocessor(); auto LE = P.getLocForEndOfToken(L); if (LE.isValid()) { // getLocWithOffset returns the location *past* the token, hence -1 auto E = LE.getLocWithOffset(-1); // TODO: Determine if it's a writable file // TODO: Determine if the location has already been touched or // needs skipping (such as in refactoring API user's code, then // the API headers need no changing since later the new API will be // in place) Replacer::instance().replace(clang::SourceRange(L, E), N, ci->getSourceManager()); } } }
std::string location(clang::SourceLocation const& l, clang::SourceManager const& sm) { if(l.isValid()) { if(l.isFileID()) { // if (sm.isLoadedFileID (sm.getFileID(l))) return "PRELOADED MODULE"; if(sm.isLoadedSourceLocation(l)) { return "PRELOADED MODULE"; } return l.printToString(sm); } if(l.isMacroID()) { // FIXME: what do we do here? somehow clang fails /* std::cout << "SLoc isMacroID\n"; auto sl = sm.getSpellingLoc(l); if (sm.isLoadedSourceLocation(sl) ) { return "PRELOADED MODULE"; } if(sl.isValid()) { return sl.printToString(sm); } PresumedLoc pl = sm.getPresumedLoc(l); if (pl.isValid()){ return string(pl.getFilename()); } */ } return string("UNKNOWN FILE"); } return string("INVALID LOC"); }
ReportStream Reporter::report(const clang::SourceRange &range) { // Track this report mTotalReports++; // Print the expansion location const clang::SourceLocation expansionLoc(mSourceManager.getExpansionLoc(range.getBegin())); std::cerr << boldCode() << expansionLoc.printToString(mSourceManager) << ": "; // Print the "connect" in a different color than warnings or errors std::cerr << connectColorCode() << "connect:" << defaultColorCode(); return ReportStream(); }
bool NamedDeclMatcher::shouldIgnore(clang::SourceLocation L) { if (!L.isValid()) { return true; } clang::SourceManager &SM = ci->getSourceManager(); clang::FullSourceLoc FSL(L, SM); const clang::FileEntry *FE = SM.getFileEntryForID(FSL.getFileID()); if (!FE) { // attempt to get the spelling location auto SL = SM.getSpellingLoc(L); if (!SL.isValid()) { return true; } clang::FullSourceLoc FSL2(SL, SM); FE = SM.getFileEntryForID(FSL2.getFileID()); if (!FE) { return true; } } auto FN = FE->getName(); for (auto I = ignoreList.begin(), E = ignoreList.end(); I != E; ++I) { if (I->FullMatch(FN)) { return true; } } return false; }
// Append a SourceLocation argument to the top trace item. void PPCallbacksTracker::appendArgument(const char *Name, clang::SourceLocation Value) { if (Value.isInvalid()) { appendArgument(Name, "(invalid)"); return; } appendArgument(Name, getSourceLocationString(PP, Value).c_str()); }
clang::Token GetTokenBefore(const clang::SourceManager &sources, clang::SourceLocation loc) { clang::Token token; token.setKind(clang::tok::unknown); clang::LangOptions lang_options; loc = loc.getLocWithOffset(-1); while (loc != sources.getLocForStartOfFile(sources.getFileID(loc))) { loc = clang::Lexer::GetBeginningOfToken(loc, sources, lang_options); if (!clang::Lexer::getRawToken(loc, token, sources, lang_options)) { if (!token.is(clang::tok::comment)) { break; } } loc = loc.getLocWithOffset(-1); } return token; }
bool HeaderTagger::isInterceptedLibHeader(const clang::SourceLocation& loc) const { if(!loc.isValid()) { return false; } auto fit = isInterceptedCache.find(sm.getFileID(loc)); if(fit != isInterceptedCache.end()) { return !fit->second.second; } std::string filename = sm.getPresumedLoc(loc).getFilename(); bool isIntercepted = isInterceptedLibHeader(filename); isInterceptedCache[sm.getFileID(loc)] = {filename, !isIntercepted}; return isIntercepted; }
clang::Token GetTokenBeforeLocation(clang::SourceLocation loc, const clang::ASTContext& ast_context) { clang::Token token; token.setKind(clang::tok::unknown); clang::LangOptions lang_options = ast_context.getLangOpts(); const clang::SourceManager& source_manager = ast_context.getSourceManager(); clang::SourceLocation file_start_loc = source_manager.getLocForStartOfFile(source_manager.getFileID(loc)); loc = loc.getLocWithOffset(-1); while (loc != file_start_loc) { loc = clang::Lexer::GetBeginningOfToken(loc, source_manager, lang_options); if (!clang::Lexer::getRawToken(loc, token, source_manager, lang_options)) { if (!token.is(clang::tok::comment)) { break; } } loc = loc.getLocWithOffset(-1); } return token; }
clang::Token GetTokenAfterLocation(clang::SourceLocation loc, const clang::SourceManager &source_manager) { clang::Token token; token.setKind(clang::tok::unknown); clang::LangOptions lang_options; loc = loc.getLocWithOffset(1); while (loc != source_manager.getLocForEndOfFile(source_manager.getFileID(loc))) { if (!clang::Lexer::getRawToken(loc, token, source_manager, lang_options)) { if (!token.is(clang::tok::comment)) { break; } loc = clang::Lexer::getLocForEndOfToken(token.getLocation(), /*Offset=*/0, source_manager, lang_options); } else { loc = loc.getLocWithOffset(1); } } return token; }
bool ClangTidyMisraCheck::isIgnored(clang::SourceLocation loc) { if (loc.isInvalid()) { return IgnoreInvalidLocations; } if (isBuiltIn(loc)) { return IgnoreBuiltInLocations; } if (isCommandLine(loc)) { return IgnoreCommandLineLocations; } return false; }
void PreprocessorCallback::HandlePPCond(clang::SourceLocation Loc, clang::SourceLocation IfLoc) { if (!Loc.isValid() || !Loc.isFileID()) return; clang::SourceManager &SM = annotator.getSourceMgr(); clang::FileID FID = SM.getFileID(Loc); if (!annotator.shouldProcess(FID)) return; while(ElifMapping.count(IfLoc)) { IfLoc = Loc; } if (SM.getFileID(IfLoc) != FID) { return; } annotator.generator(FID).addTag("span", ("data-ppcond=\"" + clang::Twine(SM.getExpansionLineNumber(IfLoc)) + "\"").str(), SM.getFileOffset(Loc), clang::Lexer::MeasureTokenLength(Loc, SM, PP.getLangOpts())); }
void PreprocessorCallback::InclusionDirective(clang::SourceLocation HashLoc, const clang::Token& IncludeTok, llvm::StringRef FileName, bool IsAngled, clang::CharSourceRange FilenameRange, const clang::FileEntry* File, llvm::StringRef SearchPath, llvm::StringRef RelativePath, const clang::Module* Imported) { if (!HashLoc.isValid() || !HashLoc.isFileID() || !File) return; clang::SourceManager &sm = annotator.getSourceMgr(); clang::FileID FID = sm.getFileID(HashLoc); if (!annotator.shouldProcess(FID)) return; std::string link = annotator.pathTo(FID, File); if (link.empty()) return; auto B = sm.getFileOffset(FilenameRange.getBegin()); auto E = sm.getFileOffset(FilenameRange.getEnd()); annotator.generator(FID).addTag("a", "href=\"" % link % "\"", B, E-B); }
void c2ffi::process_macros(clang::CompilerInstance &ci, std::ostream &os) { using namespace c2ffi; clang::SourceManager &sm = ci.getSourceManager(); clang::Preprocessor &pp = ci.getPreprocessor(); for(clang::Preprocessor::macro_iterator i = pp.macro_begin(); i != pp.macro_end(); i++) { const clang::MacroInfo *mi = (*i).second->getMacroInfo(); const clang::SourceLocation sl = mi->getDefinitionLoc(); std::string loc = sl.printToString(sm); const char *name = (*i).first->getNameStart(); if(mi->isBuiltinMacro() || loc.substr(0,10) == "<built-in>") { } else if(mi->isFunctionLike()) { } else if(best_guess type = macro_type(pp, name, mi)) { os << "/* " << loc << " */" << std::endl; os << "#define " << name << " " << macro_to_string(pp, mi) << std::endl << std::endl; } } for(clang::Preprocessor::macro_iterator i = pp.macro_begin(); i != pp.macro_end(); i++) { clang::MacroInfo *mi = (*i).second->getMacroInfo(); clang::SourceLocation sl = mi->getDefinitionLoc(); std::string loc = sl.printToString(sm); const char *name = (*i).first->getNameStart(); if(mi->isBuiltinMacro() || loc.substr(0,10) == "<built-in>") { } else if(mi->isFunctionLike()) { } else if(best_guess type = macro_type(pp, name, mi)) { output_redef(pp, name, mi, type, os); } } }
void ClangCommentPrinter::updateLastEntityLine(clang::SourceLocation Loc) { if (Loc.isInvalid()) return; const auto &Ctx = ClangLoader.getClangASTContext(); const auto &SM = Ctx.getSourceManager(); unsigned LineNo = SM.getSpellingLineNumber(Loc); clang::FileID FID = SM.getFileID(Loc); if (FID.isInvalid()) return; updateLastEntityLine(FID, LineNo); }
void EditTracker::Add(const clang::SourceManager& source_manager, clang::SourceLocation location, llvm::StringRef original_text, llvm::StringRef new_text) { llvm::StringRef filename; for (int i = 0; i < 10; i++) { filename = source_manager.getFilename(location); if (!filename.empty() || !location.isMacroID()) break; // Otherwise, no filename and the SourceLocation is a macro ID. Look one // level up the stack... location = source_manager.getImmediateMacroCallerLoc(location); } assert(!filename.empty() && "Can't track edit with no filename!"); auto result = tracked_edits_.try_emplace(original_text); if (result.second) { result.first->getValue().new_text = new_text; } result.first->getValue().filenames.try_emplace(filename); }
std::string NamedDeclMatcher::loc(clang::SourceLocation L) { return L.printToString(ci->getSourceManager()); }
string HeaderTagger::getTopLevelInclude(const clang::SourceLocation& includeLocation) const{ // if it is a dead end if (!includeLocation.isValid()) { return ""; } auto toFilename = [&] (const clang::SourceLocation& loc) { return sm.getPresumedLoc(loc).getFilename(); }; // get the presumed location (whatever this is, ask clang) ... // ~ ploc represents the file were includeLocation is located clang::PresumedLoc ploc = sm.getPresumedLoc(includeLocation); // .. and retrieve the associated include // ~ from where the file ploc represents was included clang::SourceLocation includingLocation = ploc.getIncludeLoc(); // check whether the stack can be continued if (!includingLocation.isValid()) { return ""; // this happens when element is declared in c / cpp file => no header } // ~ pIncludeLoc represents the file were includLoc is located clang::PresumedLoc pIncludeLoc = sm.getPresumedLoc(includingLocation); if( isInjectedHeader(pIncludeLoc) ){ //the header was injected -- has no valid filename ("<command line">) return ""; } //******************* // // travel down until we are at the sourcefile then work up again // if userProvided header, we need to go further // if userSearchPath/systemSearch path we need to include de header // //******************* // descent further as long as we have a header file as presumed include includeLocation if ( isHeaderFile(toFilename(includingLocation) )) { // check if last include was in the search path and next is not, // this case is a system header included inside of a programmer include chain // BUT if both are still in the search path, continue cleaning the include if (isStdLibHeader(includeLocation) && !isStdLibHeader(includingLocation)){ if(!isIntrinsicHeader(toFilename(includingLocation))) { return ploc.getFilename(); } } if (isInterceptedLibHeader(includeLocation) && !isInterceptedLibHeader(includingLocation)){ if(!isIntrinsicHeader(toFilename(includingLocation))) { return ploc.getFilename(); } } if (isUserLibHeader(includeLocation) && !isUserLibHeader(includingLocation)){ if(!isIntrinsicHeader(toFilename(includingLocation))) { return ploc.getFilename(); } } return getTopLevelInclude(includingLocation); } // we already visited all the headers and we are in the .c/.cpp file if (isHeaderFile(ploc.getFilename())) { if(isIntrinsicHeader(ploc.getFilename())) { return ploc.getFilename(); } if (isStdLibHeader(ploc.getFilename()) ) { return ploc.getFilename(); // this happens when header file is included straight in the code } if (isInterceptedLibHeader(ploc.getFilename())) { return ploc.getFilename(); // this happens when header file is included straight in the code } if (isUserLibHeader(ploc.getFilename())) { return ploc.getFilename(); } return ""; // this happens when is declared in a header which is not system header } /* // we already visited all the headers and we are in the .c/.cpp file if (!isHeaderFile(sm.getPresumedLoc(includeLoc).getFilename())) { return ploc.getFilename(); } */ return ""; }
void RefFinder::addFileLocation(clang::SourceLocation loc) { if (!loc.isFileID()) return; // skip macro expansions etc locs.push_back(loc); }
bool WebCLReporter::isFromMainFile(clang::SourceLocation location) const { return location.isValid() && instance_.getSourceManager().isFromMainFile(location); }