bool Commit::canInsertAfterToken(SourceLocation loc, FileOffset &offs, SourceLocation &AfterLoc) { if (loc.isInvalid()) return false; SourceLocation spellLoc = SourceMgr.getSpellingLoc(loc); unsigned tokLen = Lexer::MeasureTokenLength(spellLoc, SourceMgr, LangOpts); AfterLoc = loc.getLocWithOffset(tokLen); if (loc.isMacroID()) isAtEndOfMacroExpansion(loc, &loc); const SourceManager &SM = SourceMgr; while (SM.isMacroArgExpansion(loc)) loc = SM.getImmediateSpellingLoc(loc); if (loc.isMacroID()) if (!isAtEndOfMacroExpansion(loc, &loc)) return false; if (SM.isInSystemHeader(loc)) return false; loc = Lexer::getLocForEndOfToken(loc, 0, SourceMgr, LangOpts); if (loc.isInvalid()) return false; std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); if (locInfo.first.isInvalid()) return false; offs = FileOffset(locInfo.first, locInfo.second); return canInsertInOffset(loc, offs); }
void UseUsingCheck::check(const MatchFinder::MatchResult &Result) { const auto *MatchedDecl = Result.Nodes.getNodeAs<TypedefDecl>("typedef"); if (MatchedDecl->getLocation().isInvalid()) return; auto &Context = *Result.Context; auto &SM = *Result.SourceManager; SourceLocation StartLoc = MatchedDecl->getBeginLoc(); if (StartLoc.isMacroID() && IgnoreMacros) return; auto Diag = diag(StartLoc, "use 'using' instead of 'typedef'"); // do not fix if there is macro or array if (MatchedDecl->getUnderlyingType()->isArrayType() || StartLoc.isMacroID()) return; if (CheckRemoval(SM, StartLoc, Context)) { auto printPolicy = PrintingPolicy(getLangOpts()); printPolicy.SuppressScope = true; printPolicy.ConstantArraySizeAsWritten = true; printPolicy.UseVoidForZeroParams = false; Diag << FixItHint::CreateReplacement( MatchedDecl->getSourceRange(), "using " + MatchedDecl->getNameAsString() + " = " + MatchedDecl->getUnderlyingType().getAsString(printPolicy)); } }
static SourceLocation getTopMostMacro(SourceLocation Loc, SourceManager &SM) { assert(Loc.isMacroID()); SourceLocation Last; while (Loc.isMacroID()) { Last = Loc; Loc = SM.getImmediateMacroCallerLoc(Loc); } return Last; }
/// \brief For a macro \arg Loc, returns the file spelling location and sets /// to \arg isMacroArg whether the spelling resides inside a macro definition or /// a macro argument. static SourceLocation getFileSpellingLoc(SourceManager &SM, SourceLocation Loc, bool &isMacroArg) { assert(Loc.isMacroID()); SourceLocation SpellLoc = SM.getImmediateSpellingLoc(Loc); if (SpellLoc.isMacroID()) return getFileSpellingLoc(SM, SpellLoc, isMacroArg); isMacroArg = SM.isMacroArgExpansion(Loc); return SpellLoc; }
/// Returns true if the statement is expanded from a configuration macro. static bool isExpandedFromConfigurationMacro(const Stmt *S, Preprocessor &PP, bool IgnoreYES_NO = false) { // FIXME: This is not very precise. Here we just check to see if the // value comes from a macro, but we can do much better. This is likely // to be over conservative. This logic is factored into a separate function // so that we can refine it later. SourceLocation L = S->getBeginLoc(); if (L.isMacroID()) { SourceManager &SM = PP.getSourceManager(); if (IgnoreYES_NO) { // The Objective-C constant 'YES' and 'NO' // are defined as macros. Do not treat them // as configuration values. SourceLocation TopL = getTopMostMacro(L, SM); StringRef MacroName = PP.getImmediateMacroName(TopL); if (MacroName == "YES" || MacroName == "NO") return false; } else if (!PP.getLangOpts().CPlusPlus) { // Do not treat C 'false' and 'true' macros as configuration values. SourceLocation TopL = getTopMostMacro(L, SM); StringRef MacroName = PP.getImmediateMacroName(TopL); if (MacroName == "false" || MacroName == "true") return false; } return true; } return false; }
static PathDiagnosticCallPiece * getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, const SourceManager &SMgr) { SourceLocation CallLoc = CP->callEnter.asLocation(); // If the call is within a macro, don't do anything (for now). if (CallLoc.isMacroID()) return 0; assert(SMgr.isFromMainFile(CallLoc) && "The call piece should be in the main file."); // Check if CP represents a path through a function outside of the main file. if (!SMgr.isFromMainFile(CP->callEnterWithin.asLocation())) return CP; const PathPieces &Path = CP->path; if (Path.empty()) return 0; // Check if the last piece in the callee path is a call to a function outside // of the main file. if (PathDiagnosticCallPiece *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back())) { return getFirstStackedCallToHeaderFile(CPInner, SMgr); } // Otherwise, the last piece is in the main file. return 0; }
void DiagnosticRenderer::emitDiagnostic(SourceLocation Loc, DiagnosticsEngine::Level Level, StringRef Message, ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> FixItHints, const SourceManager *SM, DiagOrStoredDiag D) { assert(SM || Loc.isInvalid()); beginDiagnostic(D, Level); if (!Loc.isValid()) // If we have no source location, just emit the diagnostic message. emitDiagnosticMessage(Loc, PresumedLoc(), Level, Message, Ranges, SM, D); else { // Get the ranges into a local array we can hack on. SmallVector<CharSourceRange, 20> MutableRanges(Ranges.begin(), Ranges.end()); SmallVector<FixItHint, 8> MergedFixits; if (!FixItHints.empty()) { mergeFixits(FixItHints, *SM, LangOpts, MergedFixits); FixItHints = MergedFixits; } for (ArrayRef<FixItHint>::const_iterator I = FixItHints.begin(), E = FixItHints.end(); I != E; ++I) if (I->RemoveRange.isValid()) MutableRanges.push_back(I->RemoveRange); SourceLocation UnexpandedLoc = Loc; // Find the ultimate expansion location for the diagnostic. Loc = SM->getFileLoc(Loc); PresumedLoc PLoc = SM->getPresumedLoc(Loc, DiagOpts->ShowPresumedLoc); // First, if this diagnostic is not in the main file, print out the // "included from" lines. emitIncludeStack(Loc, PLoc, Level, *SM); // Next, emit the actual diagnostic message and caret. emitDiagnosticMessage(Loc, PLoc, Level, Message, Ranges, SM, D); emitCaret(Loc, Level, MutableRanges, FixItHints, *SM); // If this location is within a macro, walk from UnexpandedLoc up to Loc // and produce a macro backtrace. if (UnexpandedLoc.isValid() && UnexpandedLoc.isMacroID()) { unsigned MacroDepth = 0; emitMacroExpansions(UnexpandedLoc, Level, MutableRanges, FixItHints, *SM, MacroDepth); } } LastLoc = Loc; LastLevel = Level; endDiagnostic(D, Level); }
/// Finds the tokens that are consecutive (from the same FileID) /// creates a single SLocEntry, and assigns SourceLocations to each token that /// point to that SLocEntry. e.g for /// assert(foo == bar); /// There will be a single SLocEntry for the "foo == bar" chunk and locations /// for the 'foo', '==', 'bar' tokens will point inside that chunk. /// /// \arg begin_tokens will be updated to a position past all the found /// consecutive tokens. static void updateConsecutiveMacroArgTokens(SourceManager &SM, SourceLocation InstLoc, Token *&begin_tokens, Token * end_tokens) { assert(begin_tokens < end_tokens); SourceLocation FirstLoc = begin_tokens->getLocation(); SourceLocation CurLoc = FirstLoc; // Compare the source location offset of tokens and group together tokens that // are close, even if their locations point to different FileIDs. e.g. // // |bar | foo | cake | (3 tokens from 3 consecutive FileIDs) // ^ ^ // |bar foo cake| (one SLocEntry chunk for all tokens) // // we can perform this "merge" since the token's spelling location depends // on the relative offset. Token *NextTok = begin_tokens + 1; for (; NextTok < end_tokens; ++NextTok) { SourceLocation NextLoc = NextTok->getLocation(); if (CurLoc.isFileID() != NextLoc.isFileID()) break; // Token from different kind of FileID. int RelOffs; if (!SM.isInSameSLocAddrSpace(CurLoc, NextLoc, &RelOffs)) break; // Token from different local/loaded location. // Check that token is not before the previous token or more than 50 // "characters" away. if (RelOffs < 0 || RelOffs > 50) break; if (CurLoc.isMacroID() && !SM.isWrittenInSameFile(CurLoc, NextLoc)) break; // Token from a different macro. CurLoc = NextLoc; } // For the consecutive tokens, find the length of the SLocEntry to contain // all of them. Token &LastConsecutiveTok = *(NextTok-1); int LastRelOffs = 0; SM.isInSameSLocAddrSpace(FirstLoc, LastConsecutiveTok.getLocation(), &LastRelOffs); unsigned FullLength = LastRelOffs + LastConsecutiveTok.getLength(); // Create a macro expansion SLocEntry that will "contain" all of the tokens. SourceLocation Expansion = SM.createMacroArgExpansionLoc(FirstLoc, InstLoc,FullLength); // Change the location of the tokens from the spelling location to the new // expanded location. for (; begin_tokens < NextTok; ++begin_tokens) { Token &Tok = *begin_tokens; int RelOffs = 0; SM.isInSameSLocAddrSpace(FirstLoc, Tok.getLocation(), &RelOffs); Tok.setLocation(Expansion.getLocWithOffset(RelOffs)); } }
void DeprecatedIosBaseAliasesCheck::check( const MatchFinder::MatchResult &Result) { SourceManager &SM = *Result.SourceManager; const auto *Typedef = Result.Nodes.getNodeAs<TypedefDecl>("TypeDecl"); StringRef TypeName = Typedef->getName(); bool HasReplacement = ReplacementTypes.count(TypeName); const auto *TL = Result.Nodes.getNodeAs<TypeLoc>("TypeLoc"); SourceLocation IoStateLoc = TL->getBeginLoc(); // Do not generate fixits for matches depending on template arguments and // macro expansions. bool Fix = HasReplacement && !TL->getType()->isDependentType(); if (IoStateLoc.isMacroID()) { IoStateLoc = SM.getSpellingLoc(IoStateLoc); Fix = false; } SourceLocation EndLoc = IoStateLoc.getLocWithOffset(TypeName.size() - 1); if (HasReplacement) { auto FixName = ReplacementTypes.lookup(TypeName); auto Builder = diag(IoStateLoc, "'std::ios_base::%0' is deprecated; use " "'std::ios_base::%1' instead") << TypeName << FixName; if (Fix) Builder << FixItHint::CreateReplacement(SourceRange(IoStateLoc, EndLoc), FixName); } else diag(IoStateLoc, "'std::ios_base::%0' is deprecated") << TypeName; }
PathDiagnosticPiece * LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR) { const Stmt *S = BR.getStmt(); if (!S) return 0; // Here we suppress false positives coming from system macros. This list is // based on known issues. // Skip reports within the sys/queue.h macros as we do not have the ability to // reason about data structure shapes. SourceManager &SM = BRC.getSourceManager(); SourceLocation Loc = S->getLocStart(); while (Loc.isMacroID()) { if (SM.isInSystemMacro(Loc) && (SM.getFilename(SM.getSpellingLoc(Loc)).endswith("sys/queue.h"))) { BR.markInvalid(getTag(), 0); return 0; } Loc = SM.getSpellingLoc(Loc); } return 0; }
void MisleadingIndentationCheck::danglingElseCheck(const SourceManager &SM, const IfStmt *If) { SourceLocation IfLoc = If->getIfLoc(); SourceLocation ElseLoc = If->getElseLoc(); if (IfLoc.isMacroID() || ElseLoc.isMacroID()) return; if (SM.getExpansionLineNumber(If->getThen()->getLocEnd()) == SM.getExpansionLineNumber(ElseLoc)) return; if (SM.getExpansionColumnNumber(IfLoc) != SM.getExpansionColumnNumber(ElseLoc)) diag(ElseLoc, "different indentation for 'if' and corresponding 'else'"); }
/// A recursive function to trace all possible backtrace locations /// to match the \p CaretLocFileID. static SourceLocation retrieveMacroLocation(SourceLocation Loc, FileID MacroFileID, FileID CaretFileID, bool getBeginLoc, const SourceManager *SM) { if (MacroFileID == CaretFileID) return Loc; if (!Loc.isMacroID()) return SourceLocation(); SourceLocation MacroLocation, MacroArgLocation; if (SM->isMacroArgExpansion(Loc)) { MacroLocation = SM->getImmediateSpellingLoc(Loc); MacroArgLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first : SM->getImmediateExpansionRange(Loc).second; } else { MacroLocation = getBeginLoc ? SM->getImmediateExpansionRange(Loc).first : SM->getImmediateExpansionRange(Loc).second; MacroArgLocation = SM->getImmediateSpellingLoc(Loc); } MacroFileID = SM->getFileID(MacroLocation); MacroLocation = retrieveMacroLocation(MacroLocation, MacroFileID, CaretFileID, getBeginLoc, SM); if (MacroLocation.isValid()) return MacroLocation; MacroFileID = SM->getFileID(MacroArgLocation); return retrieveMacroLocation(MacroArgLocation, MacroFileID, CaretFileID, getBeginLoc, SM); }
/// \brief Computes the source location just past the end of the token at /// the given source location. If the location points at a macro, the whole /// macro expansion is skipped. SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc, SourceManager &SM, Preprocessor &PP) { if (loc.isMacroID()) loc = SM.getExpansionRange(loc).second; return PP.getLocForEndOfToken(loc); }
/// \brief Retrieve the name of the immediate macro expansion. /// /// This routine starts from a source location, and finds the name of the macro /// responsible for its immediate expansion. It looks through any intervening /// macro argument expansions to compute this. It returns a StringRef which /// refers to the SourceManager-owned buffer of the source where that macro /// name is spelled. Thus, the result shouldn't out-live that SourceManager. /// /// This differs from Lexer::getImmediateMacroName in that any macro argument /// location will result in the topmost function macro that accepted it. /// e.g. /// \code /// MAC1( MAC2(foo) ) /// \endcode /// for location of 'foo' token, this function will return "MAC1" while /// Lexer::getImmediateMacroName will return "MAC2". static StringRef getImmediateMacroName(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts) { assert(Loc.isMacroID() && "Only reasonble to call this on macros"); // Walk past macro argument expanions. while (SM.isMacroArgExpansion(Loc)) Loc = SM.getImmediateExpansionRange(Loc).first; // If the macro's spelling has no FileID, then it's actually a token paste // or stringization (or similar) and not a macro at all. if (!SM.getFileEntryForID(SM.getFileID(SM.getSpellingLoc(Loc)))) return StringRef(); // Find the spelling location of the start of the non-argument expansion // range. This is where the macro name was spelled in order to begin // expanding this macro. Loc = SM.getSpellingLoc(SM.getImmediateExpansionRange(Loc).first); // Dig out the buffer where the macro name was spelled and the extents of the // name so that we can render it into the expansion note. std::pair<FileID, unsigned> ExpansionInfo = SM.getDecomposedLoc(Loc); unsigned MacroTokenLength = Lexer::MeasureTokenLength(Loc, SM, LangOpts); StringRef ExpansionBuffer = SM.getBufferData(ExpansionInfo.first); return ExpansionBuffer.substr(ExpansionInfo.second, MacroTokenLength); }
/// A helper function to check if the current ranges are all inside the same /// macro argument expansion as Loc. static bool checkRangesForMacroArgExpansion(SourceLocation Loc, ArrayRef<CharSourceRange> Ranges, const SourceManager &SM) { assert(Loc.isMacroID() && "Must be a macro expansion!"); SmallVector<CharSourceRange, 4> SpellingRanges; mapDiagnosticRanges(Loc, Ranges, SpellingRanges, &SM); /// Count all valid ranges. unsigned ValidCount = 0; for (auto I : Ranges) if (I.isValid()) ValidCount++; if (ValidCount > SpellingRanges.size()) return false; /// To store the source location of the argument location. SourceLocation ArgumentLoc; /// Set the ArgumentLoc to the beginning location of the expansion of Loc /// so to check if the ranges expands to the same beginning location. if (!SM.isMacroArgExpansion(Loc,&ArgumentLoc)) return false; for (auto I = SpellingRanges.begin(), E = SpellingRanges.end(); I != E; ++I) { if (!checkRangeForMacroArgExpansion(*I, SM, ArgumentLoc)) return false; } return true; }
/// \brief \arg Loc is the end of a statement range. This returns the location /// of the semicolon following the statement. /// If no semicolon is found or the location is inside a macro, the returned /// source location will be invalid. SourceLocation trans::findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx) { SourceManager &SM = Ctx.getSourceManager(); if (loc.isMacroID()) { if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOpts(), &loc)) return SourceLocation(); } loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOpts()); // Break down the source location. std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc); // Try to load the file buffer. bool invalidTemp = false; StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); if (invalidTemp) return SourceLocation(); const char *tokenBegin = file.data() + locInfo.second; // Lex from the start of the given location. Lexer lexer(SM.getLocForStartOfFile(locInfo.first), Ctx.getLangOpts(), file.begin(), tokenBegin, file.end()); Token tok; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::semi)) return SourceLocation(); return tok.getLocation(); }
StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) { if (Loc.isMacroID()) return Lexer::getImmediateMacroName(Loc, getSourceManager(), getLangOpts()); SmallVector<char, 16> buf; return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts()); }
std::vector<FixItHint> QStringAllocations::fixItRawLiteral(clang::StringLiteral *lt, const string &replacement) { vector<FixItHint> fixits; SourceRange range = FixItUtils::rangeForLiteral(m_ci, lt); if (range.isInvalid()) { if (lt) { queueManualFixitWarning(lt->getLocStart(), CharPtrAllocations, "Internal error: Can't calculate source location"); } return {}; } SourceLocation start = lt->getLocStart(); if (start.isMacroID()) { queueManualFixitWarning(start, CharPtrAllocations, "Can't use QStringLiteral in macro.."); } else { string revisedReplacement = lt->getLength() == 0 ? "QLatin1String" : replacement; // QLatin1String("") is better than QStringLiteral("") if (revisedReplacement == "QStringLiteral" && lt->getLocStart().isMacroID()) { queueManualFixitWarning(lt->getLocStart(), CharPtrAllocations, "Can't use QStringLiteral in macro..."); return {}; } FixItUtils::insertParentMethodCall(revisedReplacement, range, /**by-ref*/fixits); } return fixits; }
void MisleadingIndentationCheck::missingBracesCheck(const SourceManager &SM, const CompoundStmt *CStmt) { const static StringRef StmtNames[] = {"if", "for", "while"}; for (unsigned int i = 0; i < CStmt->size() - 1; i++) { const Stmt *CurrentStmt = CStmt->body_begin()[i]; const Stmt *Inner = nullptr; int StmtKind = 0; if (const auto *CurrentIf = dyn_cast<IfStmt>(CurrentStmt)) { StmtKind = 0; Inner = CurrentIf->getElse() ? CurrentIf->getElse() : CurrentIf->getThen(); } else if (const auto *CurrentFor = dyn_cast<ForStmt>(CurrentStmt)) { StmtKind = 1; Inner = CurrentFor->getBody(); } else if (const auto *CurrentWhile = dyn_cast<WhileStmt>(CurrentStmt)) { StmtKind = 2; Inner = CurrentWhile->getBody(); } else { continue; } if (isa<CompoundStmt>(Inner)) continue; SourceLocation InnerLoc = Inner->getLocStart(); SourceLocation OuterLoc = CurrentStmt->getLocStart(); if (SM.getExpansionLineNumber(InnerLoc) == SM.getExpansionLineNumber(OuterLoc)) continue; const Stmt *NextStmt = CStmt->body_begin()[i + 1]; SourceLocation NextLoc = NextStmt->getLocStart(); if (InnerLoc.isMacroID() || OuterLoc.isMacroID() || NextLoc.isMacroID()) continue; if (SM.getExpansionColumnNumber(InnerLoc) == SM.getExpansionColumnNumber(NextLoc)) { diag(NextLoc, "misleading indentation: statement is indented too deeply"); diag(OuterLoc, "did you mean this line to be inside this '%0'", DiagnosticIDs::Note) << StmtNames[StmtKind]; } } }
void RemoveUnusedEnumMember::removeEnumConstantDecl() { SourceLocation StartLoc = (*TheEnumIterator)->getLocStart(); if (StartLoc.isMacroID()) { CharSourceRange Range = SrcManager->getExpansionRange(StartLoc); StartLoc = Range.getBegin(); } SourceLocation EndLoc = (*TheEnumIterator)->getLocEnd(); if (EndLoc.isMacroID()) { CharSourceRange Range = SrcManager->getExpansionRange(EndLoc); EndLoc = Range.getEnd(); } SourceLocation CommaLoc = Lexer::findLocationAfterToken( EndLoc, tok::comma, *SrcManager, Context->getLangOpts(), /*SkipTrailingWhitespaceAndNewLine=*/false); if (CommaLoc.isValid()) EndLoc = CommaLoc; TheRewriter.RemoveText(SourceRange(StartLoc, EndLoc)); }
// Helper function to fix up source ranges. It takes in an array of ranges, // and outputs an array of ranges where we want to draw the range highlighting // around the location specified by CaretLoc. // // To find locations which correspond to the caret, we crawl the macro caller // chain for the beginning and end of each range. If the caret location // is in a macro expansion, we search each chain for a location // in the same expansion as the caret; otherwise, we crawl to the top of // each chain. Two locations are part of the same macro expansion // iff the FileID is the same. static void mapDiagnosticRanges( SourceLocation CaretLoc, ArrayRef<CharSourceRange> Ranges, SmallVectorImpl<CharSourceRange> &SpellingRanges, const SourceManager *SM) { FileID CaretLocFileID = SM->getFileID(CaretLoc); for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { if (I->isInvalid()) continue; SourceLocation Begin = I->getBegin(), End = I->getEnd(); bool IsTokenRange = I->isTokenRange(); FileID BeginFileID = SM->getFileID(Begin); FileID EndFileID = SM->getFileID(End); // Find the common parent for the beginning and end of the range. // First, crawl the expansion chain for the beginning of the range. llvm::SmallDenseMap<FileID, SourceLocation> BeginLocsMap; while (Begin.isMacroID() && BeginFileID != EndFileID) { BeginLocsMap[BeginFileID] = Begin; Begin = SM->getImmediateExpansionRange(Begin).first; BeginFileID = SM->getFileID(Begin); } // Then, crawl the expansion chain for the end of the range. if (BeginFileID != EndFileID) { while (End.isMacroID() && !BeginLocsMap.count(EndFileID)) { End = SM->getImmediateExpansionRange(End).second; EndFileID = SM->getFileID(End); } if (End.isMacroID()) { Begin = BeginLocsMap[EndFileID]; BeginFileID = EndFileID; } } // Do the backtracking. SmallVector<FileID, 4> CommonArgExpansions; computeCommonMacroArgExpansionFileIDs(Begin, End, SM, CommonArgExpansions); Begin = retrieveMacroLocation(Begin, BeginFileID, CaretLocFileID, CommonArgExpansions, /*IsBegin=*/true, SM); End = retrieveMacroLocation(End, BeginFileID, CaretLocFileID, CommonArgExpansions, /*IsBegin=*/false, SM); if (Begin.isInvalid() || End.isInvalid()) continue; // Return the spelling location of the beginning and end of the range. Begin = SM->getSpellingLoc(Begin); End = SM->getSpellingLoc(End); SpellingRanges.push_back(CharSourceRange(SourceRange(Begin, End), IsTokenRange)); } }
/// Look through spelling locations for a macro argument expansion, and /// if found skip to it so that we can trace the argument rather than the macros /// in which that argument is used. If no macro argument expansion is found, /// don't skip anything and return the starting location. static SourceLocation skipToMacroArgExpansion(const SourceManager &SM, SourceLocation StartLoc) { for (SourceLocation L = StartLoc; L.isMacroID(); L = SM.getImmediateSpellingLoc(L)) { if (SM.isMacroArgInstantiation(L)) return L; } // Otherwise just return initial location, there's nothing to skip. return StartLoc; }
/// Get the presumed location of a diagnostic message. This computes the /// presumed location for the top of any macro backtrace when present. static PresumedLoc getDiagnosticPresumedLoc(const SourceManager &SM, SourceLocation Loc) { // This is a condensed form of the algorithm used by EmitCaretDiagnostic to // walk to the top of the macro call stack. while (Loc.isMacroID()) { Loc = skipToMacroArgExpansion(SM, Loc); Loc = getImmediateMacroCallerLoc(SM, Loc); } return SM.getPresumedLoc(Loc); }
static bool LineIsMarkedWithNOLINTinMacro(SourceManager &SM, SourceLocation Loc) { while (true) { if (LineIsMarkedWithNOLINT(SM, Loc)) return true; if (!Loc.isMacroID()) return false; Loc = SM.getImmediateExpansionRange(Loc).first; } return false; }
void ReplaceAutoPtrCheck::check(const MatchFinder::MatchResult &Result) { SourceManager &SM = *Result.SourceManager; if (const auto *E = Result.Nodes.getNodeAs<Expr>(AutoPtrOwnershipTransferId)) { CharSourceRange Range = Lexer::makeFileCharRange( CharSourceRange::getTokenRange(E->getSourceRange()), SM, LangOptions()); if (Range.isInvalid()) return; auto Diag = diag(Range.getBegin(), "use std::move to transfer ownership") << FixItHint::CreateInsertion(Range.getBegin(), "std::move(") << FixItHint::CreateInsertion(Range.getEnd(), ")"); if (auto Fix = Inserter->CreateIncludeInsertion(SM.getMainFileID(), "utility", /*IsAngled=*/true)) Diag << *Fix; return; } SourceLocation AutoPtrLoc; if (const auto *TL = Result.Nodes.getNodeAs<TypeLoc>(AutoPtrTokenId)) { // std::auto_ptr<int> i; // ^ if (auto Loc = TL->getAs<TemplateSpecializationTypeLoc>()) AutoPtrLoc = Loc.getTemplateNameLoc(); } else if (const auto *D = Result.Nodes.getNodeAs<UsingDecl>(AutoPtrTokenId)) { // using std::auto_ptr; // ^ AutoPtrLoc = D->getNameInfo().getBeginLoc(); } else { llvm_unreachable("Bad Callback. No node provided."); } if (AutoPtrLoc.isMacroID()) AutoPtrLoc = SM.getSpellingLoc(AutoPtrLoc); // Ensure that only the 'auto_ptr' token is replaced and not the template // aliases. if (StringRef(SM.getCharacterData(AutoPtrLoc), strlen("auto_ptr")) != "auto_ptr") return; SourceLocation EndLoc = AutoPtrLoc.getLocWithOffset(strlen("auto_ptr") - 1); diag(AutoPtrLoc, "auto_ptr is deprecated, use unique_ptr instead") << FixItHint::CreateReplacement(SourceRange(AutoPtrLoc, EndLoc), "unique_ptr"); }
/// Walk up the chain of macro expansions and collect the FileIDs identifying the /// expansions. static void getMacroArgExpansionFileIDs(SourceLocation Loc, SmallVectorImpl<FileID> &IDs, bool IsBegin, const SourceManager *SM) { while (Loc.isMacroID()) { if (SM->isMacroArgExpansion(Loc)) { IDs.push_back(SM->getFileID(Loc)); Loc = SM->getImmediateSpellingLoc(Loc); } else { auto ExpRange = SM->getImmediateExpansionRange(Loc); Loc = IsBegin ? ExpRange.first : ExpRange.second; } } }
// Looks for the token matching the predicate and returns the range of the found // token including trailing whitespace. static SourceRange FindToken(const SourceManager &Sources, LangOptions LangOpts, SourceLocation StartLoc, SourceLocation EndLoc, bool (*Pred)(const Token &)) { if (StartLoc.isMacroID() || EndLoc.isMacroID()) return SourceRange(); FileID File = Sources.getFileID(Sources.getSpellingLoc(StartLoc)); StringRef Buf = Sources.getBufferData(File); const char *StartChar = Sources.getCharacterData(StartLoc); Lexer Lex(StartLoc, LangOpts, StartChar, StartChar, Buf.end()); Lex.SetCommentRetentionState(true); Token Tok; do { Lex.LexFromRawLexer(Tok); if (Pred(Tok)) { Token NextTok; Lex.LexFromRawLexer(NextTok); return SourceRange(Tok.getLocation(), NextTok.getLocation()); } } while (Tok.isNot(tok::eof) && Tok.getLocation() < EndLoc); return SourceRange(); }
void SimplifyCommaExpr::simplifyCommaExpr(void) { TransAssert((TheBinaryOperator->getOpcode() == clang::BO_Comma) && "Non Comma Operator!"); const Expr *LHS = TheBinaryOperator->getLHS(); std::string LHSStr; RewriteHelper->getExprString(LHS, LHSStr); SourceRange LHSRange = LHS->getSourceRange(); SourceLocation StartLoc = LHSRange.getBegin(); SourceLocation EndLoc; if (StartLoc.isMacroID()) { StartLoc = SrcManager->getFileLoc(StartLoc); EndLoc = LHSRange.getEnd(); TransAssert(EndLoc.isMacroID() && "EndLoc is not from a macro!"); LHSRange = SourceRange(StartLoc, SrcManager->getFileLoc(EndLoc)); } EndLoc = RewriteHelper->getEndLocationUntil(LHSRange, ','); TheRewriter.RemoveText(SourceRange(StartLoc, EndLoc)); LHSStr += ";"; RewriteHelper->addStringBeforeStmt(TheStmt, LHSStr, NeedParen); }
/// Gets the location of the immediate macro caller, one level up the stack /// toward the initial macro typed into the source. static SourceLocation getImmediateMacroCallerLoc(const SourceManager &SM, SourceLocation Loc) { if (!Loc.isMacroID()) return Loc; // When we have the location of (part of) an expanded parameter, its spelling // location points to the argument as typed into the macro call, and // therefore is used to locate the macro caller. if (SM.isMacroArgInstantiation(Loc)) return SM.getImmediateSpellingLoc(Loc); // Otherwise, the caller of the macro is located where this macro is // expanded (while the spelling is part of the macro definition). return SM.getImmediateInstantiationRange(Loc).first; }
/// Gets the location of the immediate macro callee, one level down the stack /// toward the leaf macro. static SourceLocation getImmediateMacroCalleeLoc(const SourceManager &SM, SourceLocation Loc) { if (!Loc.isMacroID()) return Loc; // When we have the location of (part of) an expanded parameter, its // expansion location points to the unexpanded paramater reference within // the macro definition (or callee). if (SM.isMacroArgInstantiation(Loc)) return SM.getImmediateInstantiationRange(Loc).first; // Otherwise, the callee of the macro is located where this location was // spelled inside the macro definition. return SM.getImmediateSpellingLoc(Loc); }