From: Douglas Gregor Date: Fri, 12 Nov 2010 07:15:47 +0000 (+0000) Subject: Make sure to always check the result of X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb7b1e17b63967317ab5cc55682168cf0380519a;p=clang Make sure to always check the result of SourceManager::getPresumedLoc(), so that we don't try to make use of an invalid presumed location. Doing so can cause crashes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118885 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 4f5c17344d..d5e41de25f 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -724,6 +724,11 @@ public: /// /// Note that a presumed location is always given as the instantiation point /// of an instantiation location, not at the spelling location. + /// + /// \returns The presumed location of the specified SourceLocation. If the + /// presumed location cannot be calculate (e.g., because \p Loc is invalid + /// or the file containing \p Loc has changed on disk), returns an invalid + /// presumed location. PresumedLoc getPresumedLoc(SourceLocation Loc) const; /// isFromSameFile - Returns true if both SourceLocations correspond to diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 8b3ad5a61f..afc9b509e7 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -169,15 +169,15 @@ namespace { void StmtDumper::DumpLocation(SourceLocation Loc) { SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); - if (SpellingLoc.isInvalid()) { - OS << ""; - return; - } - // The general format we print out is filename:line:col, but we drop pieces // that haven't changed since the last loc printed. PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc); + if (PLoc.isInvalid()) { + OS << ""; + return; + } + if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) { OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 2e7e06fef7..b405db4bce 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -481,9 +481,9 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { if (!HasKindDecoration) OS << " " << D->getKindName(); - if (D->getLocation().isValid()) { - PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( + PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc( D->getLocation()); + if (PLoc.isValid()) { OS << " at " << PLoc.getFilename() << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); diff --git a/lib/Basic/SourceLocation.cpp b/lib/Basic/SourceLocation.cpp index 7412b95560..1571e2205f 100644 --- a/lib/Basic/SourceLocation.cpp +++ b/lib/Basic/SourceLocation.cpp @@ -43,6 +43,11 @@ void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ if (isFileID()) { PresumedLoc PLoc = SM.getPresumedLoc(*this); + + if (PLoc.isInvalid()) { + OS << ""; + return; + } // The instantiation and spelling pos is identical for file locs. OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); diff --git a/lib/Checker/AnalysisConsumer.cpp b/lib/Checker/AnalysisConsumer.cpp index e1591a6a64..16ad5a7ef1 100644 --- a/lib/Checker/AnalysisConsumer.cpp +++ b/lib/Checker/AnalysisConsumer.cpp @@ -143,19 +143,21 @@ public: SourceManager &SM = Mgr->getASTContext().getSourceManager(); PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); - llvm::errs() << "ANALYZE: " << Loc.getFilename(); + if (Loc.isValid()) { + llvm::errs() << "ANALYZE: " << Loc.getFilename(); - if (isa(D) || isa(D)) { - const NamedDecl *ND = cast(D); - llvm::errs() << ' ' << ND << '\n'; - } - else if (isa(D)) { - llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" - << Loc.getColumn() << '\n'; - } - else if (const ObjCMethodDecl *MD = dyn_cast(D)) { - Selector S = MD->getSelector(); - llvm::errs() << ' ' << S.getAsString(); + if (isa(D) || isa(D)) { + const NamedDecl *ND = cast(D); + llvm::errs() << ' ' << ND << '\n'; + } + else if (isa(D)) { + llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:" + << Loc.getColumn() << '\n'; + } + else if (const ObjCMethodDecl *MD = dyn_cast(D)) { + Selector S = MD->getSelector(); + llvm::errs() << ' ' << S.getAsString(); + } } } diff --git a/lib/Checker/AnalyzerStatsChecker.cpp b/lib/Checker/AnalyzerStatsChecker.cpp index 9badb79625..c484537e95 100644 --- a/lib/Checker/AnalyzerStatsChecker.cpp +++ b/lib/Checker/AnalyzerStatsChecker.cpp @@ -83,16 +83,18 @@ void AnalyzerStatsChecker::VisitEndAnalysis(ExplodedGraph &G, llvm::SmallString<128> buf; llvm::raw_svector_ostream output(buf); PresumedLoc Loc = SM.getPresumedLoc(D->getLocation()); - output << Loc.getFilename() << " : "; + if (Loc.isValid()) { + output << Loc.getFilename() << " : "; - if (isa(D) || isa(D)) { - const NamedDecl *ND = cast(D); - output << ND; - } - else if (isa(D)) { - output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn(); + if (isa(D) || isa(D)) { + const NamedDecl *ND = cast(D); + output << ND; + } + else if (isa(D)) { + output << "block(line:" << Loc.getLine() << ":col:" << Loc.getColumn(); + } } - + output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: " << unreachable << " | Aborted Block: " << (Eng.wasBlockAborted() ? "yes" : "no") diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp index 2f7e995b20..b24ece5119 100644 --- a/lib/Frontend/DocumentXML.cpp +++ b/lib/Frontend/DocumentXML.cpp @@ -327,9 +327,11 @@ PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc) if (!SpellingLoc.isInvalid()) { PLoc = SM.getPresumedLoc(SpellingLoc); - addSourceFileAttribute(PLoc.getFilename()); - addAttribute("line", PLoc.getLine()); - addAttribute("col", PLoc.getColumn()); + if (PLoc.isValid()) { + addSourceFileAttribute(PLoc.getFilename()); + addAttribute("line", PLoc.getLine()); + addAttribute("col", PLoc.getColumn()); + } } // else there is no error in some cases (eg. CXXThisExpr) return PLoc; @@ -346,8 +348,9 @@ void DocumentXML::addLocationRange(const SourceRange& R) if (!SpellingLoc.isInvalid()) { PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc); - if (PStartLoc.isInvalid() || - strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { + if (PLoc.isInvalid()) { + } else if (PStartLoc.isInvalid() || + strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) { addToMap(SourceFiles, PLoc.getFilename(), ID_FILE); addAttribute("endfile", PLoc.getFilename()); addAttribute("endline", PLoc.getLine()); diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 6019b30833..429999cd5e 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -131,7 +131,10 @@ public: bool HandleFirstTokOnLine(Token &Tok); bool MoveToLine(SourceLocation Loc) { - return MoveToLine(SM.getPresumedLoc(Loc).getLine()); + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + if (PLoc.isInvalid()) + return false; + return MoveToLine(PLoc.getLine()); } bool MoveToLine(unsigned LineNo); @@ -238,10 +241,13 @@ void PrintPPOutputPPCallbacks::FileChanged(SourceLocation Loc, SourceManager &SourceMgr = SM; PresumedLoc UserLoc = SourceMgr.getPresumedLoc(Loc); + if (UserLoc.isInvalid()) + return; + unsigned NewLine = UserLoc.getLine(); if (Reason == PPCallbacks::EnterFile) { - SourceLocation IncludeLoc = SourceMgr.getPresumedLoc(Loc).getIncludeLoc(); + SourceLocation IncludeLoc = UserLoc.getIncludeLoc(); if (IncludeLoc.isValid()) MoveToLine(IncludeLoc); } else if (Reason == PPCallbacks::SystemHeaderPragma) { @@ -593,10 +599,18 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, // start. const SourceManager &SourceMgr = PP.getSourceManager(); Token Tok; - do PP.Lex(Tok); - while (Tok.isNot(tok::eof) && Tok.getLocation().isFileID() && - !strcmp(SourceMgr.getPresumedLoc(Tok.getLocation()).getFilename(), - "")); + do { + PP.Lex(Tok); + if (Tok.is(tok::eof) || !Tok.getLocation().isFileID()) + break; + + PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); + if (PLoc.isInvalid()) + break; + + if (strcmp(PLoc.getFilename(), "")) + break; + } while (true); // Read all the preprocessed tokens, printing them out to the stream. PrintPreprocessedTokens(PP, Tok, Callbacks, *OS); diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 9e450d25c3..4fd0552bac 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -57,7 +57,9 @@ PrintIncludeStack(SourceLocation Loc, const SourceManager &SM) { if (Loc.isInvalid()) return; PresumedLoc PLoc = SM.getPresumedLoc(Loc); - + if (PLoc.isInvalid()) + return; + // Print out the other include frames first. PrintIncludeStack(PLoc.getIncludeLoc(), SM); @@ -328,7 +330,9 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, if (!Suppressed) { // Get the pretty name, according to #line directives etc. PresumedLoc PLoc = SM.getPresumedLoc(Loc); - + if (PLoc.isInvalid()) + return; + // If this diagnostic is not in the main file, print out the // "included from" lines. if (LastWarningLoc != PLoc.getIncludeLoc()) { @@ -567,6 +571,10 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc, // We specifically do not do word-wrapping or tab-expansion here, // because this is supposed to be easy to parse. + PresumedLoc PLoc = SM.getPresumedLoc(B); + if (PLoc.isInvalid()) + break; + OS << "fix-it:\""; OS.write_escaped(SM.getPresumedLoc(B).getFilename()); OS << "\":{" << SM.getLineNumber(BInfo.first, BInfo.second) @@ -770,6 +778,9 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, if (Info.getLocation().isValid()) { const SourceManager &SM = Info.getLocation().getManager(); PresumedLoc PLoc = SM.getPresumedLoc(Info.getLocation()); + if (PLoc.isInvalid()) + return; + unsigned LineNo = PLoc.getLine(); // First, if this diagnostic is not in the main file, print out the diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 7d428402db..7aa3b31bc7 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -804,7 +804,9 @@ static bool ReadLineMarkerFlags(bool &IsFileEntry, bool &IsFileExit, FileID CurFileID = SM.getDecomposedInstantiationLoc(FlagTok.getLocation()).first; PresumedLoc PLoc = SM.getPresumedLoc(FlagTok.getLocation()); - + if (PLoc.isInvalid()) + return true; + // If there is no include loc (main file) or if the include loc is in a // different physical file, then we aren't in a "1" line marker flag region. SourceLocation IncLoc = PLoc.getIncludeLoc(); diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index b779dd5654..2428f9af45 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -723,7 +723,7 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { PresumedLoc PLoc = SourceMgr.getPresumedLoc(Loc); // __LINE__ expands to a simple numeric value. - OS << PLoc.getLine(); + OS << (PLoc.isValid()? PLoc.getLine() : 1); Tok.setKind(tok::numeric_constant); } else if (II == Ident__FILE__ || II == Ident__BASE_FILE__) { // C99 6.10.8: "__FILE__: The presumed name of the current source file (a @@ -732,19 +732,24 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { // __BASE_FILE__ is a GNU extension that returns the top of the presumed // #include stack instead of the current file. - if (II == Ident__BASE_FILE__) { + if (II == Ident__BASE_FILE__ && PLoc.isValid()) { SourceLocation NextLoc = PLoc.getIncludeLoc(); while (NextLoc.isValid()) { PLoc = SourceMgr.getPresumedLoc(NextLoc); + if (PLoc.isInvalid()) + break; + NextLoc = PLoc.getIncludeLoc(); } } // Escape this filename. Turn '\' -> '\\' '"' -> '\"' llvm::SmallString<128> FN; - FN += PLoc.getFilename(); - Lexer::Stringify(FN); - OS << '"' << FN.str() << '"'; + if (PLoc.isValid()) { + FN += PLoc.getFilename(); + Lexer::Stringify(FN); + OS << '"' << FN.str() << '"'; + } Tok.setKind(tok::string_literal); } else if (II == Ident__DATE__) { if (!DATELoc.isValid()) @@ -770,9 +775,11 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { unsigned Depth = 0; PresumedLoc PLoc = SourceMgr.getPresumedLoc(Tok.getLocation()); - PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); - for (; PLoc.isValid(); ++Depth) + if (PLoc.isValid()) { PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); + for (; PLoc.isValid(); ++Depth) + PLoc = SourceMgr.getPresumedLoc(PLoc.getIncludeLoc()); + } // __INCLUDE_LEVEL__ expands to a simple numeric value. OS << Depth; diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 8d469f609d..58625520a9 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -329,6 +329,9 @@ void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) { PresumedLoc PLoc = SourceMgr.getPresumedLoc(SysHeaderTok.getLocation()); + if (PLoc.isInvalid()) + return; + unsigned FilenameLen = strlen(PLoc.getFilename()); unsigned FilenameID = SourceMgr.getLineTableFilenameID(PLoc.getFilename(), FilenameLen); diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp index e86323956f..55edc1e3f3 100644 --- a/tools/libclang/CIndexInclusionStack.cpp +++ b/tools/libclang/CIndexInclusionStack.cpp @@ -55,7 +55,7 @@ void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB, while (L.isValid()) { PresumedLoc PLoc = SM.getPresumedLoc(L); InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L)); - L = PLoc.getIncludeLoc(); + L = PLoc.isValid()? PLoc.getIncludeLoc() : SourceLocation(); } // Callback to the client.