SourceLoc ClangDiagnosticConsumer::resolveSourceLocation( const clang::SourceManager &clangSrcMgr, clang::SourceLocation clangLoc) { SourceManager &swiftSrcMgr = ImporterImpl.SwiftContext.SourceMgr; SourceLoc loc; clangLoc = clangSrcMgr.getFileLoc(clangLoc); auto decomposedLoc = clangSrcMgr.getDecomposedLoc(clangLoc); if (decomposedLoc.first.isInvalid()) return loc; auto buffer = clangSrcMgr.getBuffer(decomposedLoc.first); unsigned mirrorID; auto mirrorIter = mirroredBuffers.find(buffer); if (mirrorIter != mirroredBuffers.end()) { mirrorID = mirrorIter->second; } else { std::unique_ptr<llvm::MemoryBuffer> mirrorBuffer{ llvm::MemoryBuffer::getMemBuffer(buffer->getBuffer(), buffer->getBufferIdentifier(), /*nullTerminated=*/true) }; mirrorID = swiftSrcMgr.addNewSourceBuffer(std::move(mirrorBuffer)); mirroredBuffers[buffer] = mirrorID; } loc = swiftSrcMgr.getLocForOffset(mirrorID, decomposedLoc.second); auto presumedLoc = clangSrcMgr.getPresumedLoc(clangLoc); if (!presumedLoc.getFilename()) return loc; if (presumedLoc.getLine() == 0) return SourceLoc(); unsigned bufferLineNumber = clangSrcMgr.getLineNumber(decomposedLoc.first, decomposedLoc.second); StringRef presumedFile = presumedLoc.getFilename(); SourceLoc startOfLine = loc.getAdvancedLoc(-presumedLoc.getColumn() + 1); bool isNewVirtualFile = swiftSrcMgr.openVirtualFile(startOfLine, presumedFile, presumedLoc.getLine() - bufferLineNumber); if (isNewVirtualFile) { SourceLoc endOfLine = findEndOfLine(swiftSrcMgr, loc, mirrorID); swiftSrcMgr.closeVirtualFile(endOfLine); } using SourceManagerRef = llvm::IntrusiveRefCntPtr<const clang::SourceManager>; auto iter = std::lower_bound(sourceManagersWithDiagnostics.begin(), sourceManagersWithDiagnostics.end(), &clangSrcMgr, [](const SourceManagerRef &inArray, const clang::SourceManager *toInsert) { return std::less<const clang::SourceManager *>()(inArray.get(), toInsert); }); if (iter->get() != &clangSrcMgr) sourceManagersWithDiagnostics.insert(iter, &clangSrcMgr); return loc; }
// Get the source range of the macro definition excluding the #define. SrcRange getMacroRange(const clang::MacroInfo *MI, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(MI->getDefinitionLoc()); clang::SourceLocation ELoc = sm.getExpansionLoc(MI->getDefinitionEndLoc()); return constructSrcRange(sm, options, SLoc, ELoc); }
int getLineCount(clang::SourceRange sourceRange, const clang::SourceManager& sourceManager) { clang::SourceLocation startLocation = sourceRange.getBegin(); clang::SourceLocation endLocation = sourceRange.getEnd(); unsigned startLineNumber = sourceManager.getPresumedLineNumber(startLocation); unsigned endLineNumber = sourceManager.getPresumedLineNumber(endLocation); return endLineNumber - startLineNumber + 1; }
// Get the source range of the specified Stmt. SrcRange getStmtRange(const clang::Stmt *S, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(S->getLocStart()); clang::SourceLocation ELoc = sm.getExpansionLoc(S->getLocEnd()); // This is necessary to get the correct range of function-like macros. if (SLoc == ELoc && S->getLocEnd().isMacroID()) ELoc = sm.getExpansionRange(S->getLocEnd()).second; return constructSrcRange(sm, options, SLoc, ELoc); }
bool VisitDecl(clang::Decl *decl) { if (markedAsSuppress(decl, _rule)) { clang::SourceLocation startLocation = decl->getLocStart(); clang::SourceLocation endLocation = decl->getLocEnd(); unsigned startLineNumber = _sourceManager->getPresumedLineNumber(startLocation); unsigned endLineNumber = _sourceManager->getPresumedLineNumber(endLocation); _range.insert(std::make_pair(startLineNumber, endLineNumber)); } return true; }
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"); }
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 GenericAstNode::getRangeInMainFile(std::pair<int, int> &result, clang::SourceManager const &manager, clang::ASTContext &context) { auto range = getRange(); if (range.isInvalid()) { return false; } auto start = manager.getDecomposedSpellingLoc(range.getBegin()); auto end = manager.getDecomposedSpellingLoc(clang::Lexer::getLocForEndOfToken(range.getEnd(), 0, manager, context.getLangOpts())); if (start.first != end.first || start.first != manager.getMainFileID()) { //Not in the same file, or not in the main file (probably #included) return false; } result = std::make_pair(start.second, end.second); return true; }
ast::SourceOffsetRanges getStmtSpecificOffsetRanges(clang::SourceManager& sourceManager, clang::Stmt& stmt) { auto tryStmt = clang::dyn_cast<clang::CXXTryStmt>(&stmt); if (!tryStmt) return {}; auto catchStmt = tryStmt->getHandler(0); std::array<std::array<clang::SourceLocation, 2>, 3> locRanges = { { { tryStmt->getTryLoc(), tryStmt->getTryBlock()->getLBracLoc().getLocWithOffset(1) }, { catchStmt->getCatchLoc(), catchStmt->getHandlerBlock()->getLocStart().getLocWithOffset(1) }, { catchStmt->getHandlerBlock()->getLocEnd(), catchStmt->getHandlerBlock()->getLocEnd().getLocWithOffset(1) } } }; ast::SourceOffsetRanges ranges; ranges.reserve(locRanges.size()); for (auto const& r : locRanges) ranges.emplace_back(sourceManager.getFileOffset(r[0]), sourceManager.getFileOffset(r[1])); return ranges; }
string Utils::filenameForLoc(SourceLocation loc, const clang::SourceManager &sm) { string filename = sm.getFilename(loc); auto splitted = clazy_std::splitString(filename, '/'); if (splitted.empty()) return {}; return splitted[splitted.size() - 1]; }
SrcRange constructSrcRange(const clang::SourceManager& sm, const clang::LangOptions& options, const clang::SourceLocation& SLoc, const clang::SourceLocation& ELoc) { unsigned start = sm.getFileOffset(SLoc); unsigned end = sm.getFileOffset(ELoc); end += clang::Lexer::MeasureTokenLength(ELoc, sm, options); return SrcRange(start, end); }
std::string MocNg::GetTag(clang::SourceLocation DeclLoc, const clang::SourceManager &SM) { clang::SourceLocation FileLoc = SM.getFileLoc(DeclLoc); clang::FileID FID = SM.getFileID(FileLoc); const llvm::MemoryBuffer *Buffer = SM.getBuffer(FID); const char *B = Buffer->getBufferStart(); int Off = SM.getFileOffset(FileLoc); int Orig = Off; while (Off > 0 && B[Off] != ';' && B[Off]!=',' && B[Off] != '}' && B[Off] != ':' /*&& B[Off] != '\n'*/ ) { Off--; } auto it_before = Tags.lower_bound(FileLoc.getLocWithOffset(Off - Orig)); auto it_after = Tags.upper_bound(FileLoc); if (it_before != Tags.end() && it_after != Tags.begin() && it_before == (--it_after)) { return it_before->second; } return {}; }
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); }
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; }
RangeSet collect(clang::ASTContext &astContext, oclint::RuleBase *rule) { _rule = rule; _sourceManager = &astContext.getSourceManager(); _range.clear(); clang::DeclContext *decl = astContext.getTranslationUnitDecl(); for (clang::DeclContext::decl_iterator declIt = decl->decls_begin(), declEnd = decl->decls_end(); declIt != declEnd; ++declIt) { clang::SourceLocation startLocation = (*declIt)->getLocStart(); if (startLocation.isValid() && _sourceManager->getMainFileID() == _sourceManager->getFileID(startLocation)) { (void) /* explicitly ignore the return of this function */ clang::RecursiveASTVisitor<DeclAnnotationRangeCollector>::TraverseDecl(*declIt); } } return _range; }
// Get the source range of the specified Stmt, ensuring that a semicolon is // included, if necessary - since the clang ranges do not guarantee this. SrcRange getStmtRangeWithSemicolon(const clang::Stmt *S, const clang::SourceManager& sm, const clang::LangOptions& options) { clang::SourceLocation SLoc = sm.getExpansionLoc(S->getLocStart()); clang::SourceLocation ELoc = sm.getExpansionLoc(S->getLocEnd()); unsigned start = sm.getFileOffset(SLoc); unsigned end = sm.getFileOffset(ELoc); // Below code copied from clang::Lexer::MeasureTokenLength(): clang::SourceLocation Loc = sm.getExpansionLoc(ELoc); std::pair<clang::FileID, unsigned> LocInfo = sm.getDecomposedLoc(Loc); llvm::StringRef Buffer = sm.getBufferData(LocInfo.first); const char *StrData = Buffer.data()+LocInfo.second; clang::Lexer TheLexer(Loc, options, Buffer.begin(), StrData, Buffer.end()); clang::Token TheTok; TheLexer.LexFromRawLexer(TheTok); // End copied code. end += TheTok.getLength(); // Check if we the source range did include the semicolon. if (TheTok.isNot(clang::tok::semi) && TheTok.isNot(clang::tok::r_brace)) { TheLexer.LexFromRawLexer(TheTok); if (TheTok.is(clang::tok::semi)) { end += TheTok.getLength(); } } return SrcRange(start, end); }
SourceLocation Utils::locForNextToken(SourceLocation loc, const clang::SourceManager &sm, const clang::LangOptions &lo) { std::pair<FileID, unsigned> locInfo = sm.getDecomposedLoc(loc); bool InvalidTemp = false; StringRef File = sm.getBufferData(locInfo.first, &InvalidTemp); if (InvalidTemp) { llvm::errs() << "Failed to get buffer data\n"; return {}; } const char *TokenBegin = File.data() + locInfo.second; Lexer lexer(sm.getLocForStartOfFile(locInfo.first), lo, File.begin(), TokenBegin, File.end()); Token Tok; lexer.LexFromRawLexer(Tok); SourceLocation TokenLoc = Tok.getLocation(); // Calculate how much whitespace needs to be skipped if any. unsigned NumWhitespaceChars = 0; const char *TokenEnd = sm.getCharacterData(TokenLoc) + Tok.getLength(); unsigned char C = *TokenEnd; while (isHorizontalWhitespace(C)) { C = *(++TokenEnd); NumWhitespaceChars++; } // Skip \r, \n, \r\n, or \n\r if (C == '\n' || C == '\r') { char PrevC = C; C = *(++TokenEnd); NumWhitespaceChars++; if ((C == '\n' || C == '\r') && C != PrevC) NumWhitespaceChars++; } return loc.getLocWithOffset(Tok.getLength() + NumWhitespaceChars); }
core::annotations::Location convertClangSrcLoc(core::NodeManager& man, const clang::SourceManager& sm, clang::SourceLocation start, clang::SourceLocation end) { // check file validity FileID&& fileId = sm.getFileID(start); if(fileId.isInvalid()) return core::annotations::Location::getShared(); const clang::FileEntry* fileEntry = sm.getFileEntryForID(fileId); // if we cannot get the file entry, lets try to get the source filename directly std::string filename; if(!fileEntry) { StringRef s = sm.getFilename(start); filename = s.str(); } else { assert_true(fileEntry); filename = fileEntry->getName(); } // update macro locations, if required start = getExpansionLoc(sm, start); end = getExpansionLoc(sm, end); // generate location object core::IRBuilder builder(man); return core::annotations::Location(builder.stringValue(filename.c_str()), core::annotations::TextPosition(sm.getSpellingLineNumber(start), sm.getSpellingColumnNumber(start)), core::annotations::TextPosition(sm.getSpellingLineNumber(end), sm.getSpellingColumnNumber(end))); }
bool mergeAndDeduplicate(const TUReplacements &TUs, FileToReplacementsMap &GroupedReplacements, clang::SourceManager &SM) { // Group all replacements by target file. std::set<StringRef> Warned; for (const auto &TU : TUs) { for (const tooling::Replacement &R : TU.Replacements) { // Use the file manager to deduplicate paths. FileEntries are // automatically canonicalized. const FileEntry *Entry = SM.getFileManager().getFile(R.getFilePath()); if (!Entry && Warned.insert(R.getFilePath()).second) { errs() << "Described file '" << R.getFilePath() << "' doesn't exist. Ignoring...\n"; continue; } GroupedReplacements[Entry].push_back(R); } } // Ask clang to deduplicate and report conflicts. return !deduplicateAndDetectConflicts(GroupedReplacements, SM); }
clang::SourceLocation getExpansionLoc(const clang::SourceManager& sm, clang::SourceLocation loc) { if(sm.isMacroArgExpansion(loc)) { loc = sm.getExpansionLoc(loc); } return loc; }
std::string locationToString(clang::SourceLocation loc, clang::SourceManager& sm) { clang::PresumedLoc fixed = sm.getPresumedLoc(loc); if (!fixed.isValid()) return "???"; return (llvm::Twine(fixed.getFilename()) + ":" + llvm::Twine(fixed.getLine())).str(); }