From 24146975f1af8c1b4b14e8545f218129d0e7dfeb Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Thu, 22 Aug 2013 00:27:10 +0000 Subject: [PATCH] Split isFromMainFile into two functions. Basically, isInMainFile considers line markers, and isWrittenInMainFile doesn't. Distinguishing between the two is useful when dealing with files which are preprocessed files or rewritten with -frewrite-includes (so we don't, for example, print useless warnings). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188968 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/SourceManager.h | 26 +++++++++++++++---- lib/Frontend/VerifyDiagnosticConsumer.cpp | 4 +-- lib/Lex/PPDirectives.cpp | 2 +- lib/Rewrite/Frontend/RewriteMacros.cpp | 2 +- lib/Rewrite/Frontend/RewriteModernObjC.cpp | 2 +- lib/Rewrite/Frontend/RewriteObjC.cpp | 2 +- lib/Sema/Sema.cpp | 4 +-- lib/Sema/SemaChecking.cpp | 2 +- lib/Sema/SemaDeclCXX.cpp | 2 +- lib/Sema/SemaExpr.cpp | 2 +- lib/StaticAnalyzer/Core/BugReporter.cpp | 2 +- lib/StaticAnalyzer/Core/CallEvent.cpp | 4 +-- .../Core/ExprEngineCallAndReturn.cpp | 2 +- lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 4 +-- .../Frontend/AnalysisConsumer.cpp | 2 +- test/Preprocessor/warn-macro-unused.c | 4 +++ test/Sema/inline.c | 13 ++++++++++ .../warn-using-namespace-in-header.cpp | 9 +++++++ tools/libclang/CXSourceLocation.cpp | 2 +- 19 files changed, 66 insertions(+), 24 deletions(-) diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 9fc4885220..c2bf2c5da0 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -1292,14 +1292,30 @@ public: PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives = true) const; - /// \brief Returns true if both SourceLocations correspond to the same file. - bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const { + /// \brief Returns whether the PresumedLoc for a given SourceLocation is + /// in the main file. + /// + /// This computes the "presumed" location for a SourceLocation, then checks + /// whether it came from a file other than the main file. This is different + /// from isWrittenInMainFile() because it takes line marker directives into + /// account. + bool isInMainFile(SourceLocation Loc) const { + return getPresumedLoc(Loc).getIncludeLoc().isInvalid(); + } + + /// \brief Returns true if the spelling locations for both SourceLocations + /// are part of the same file buffer. + /// + /// This check ignores line marker directives. + bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const { return getFileID(Loc1) == getFileID(Loc2); } - /// \brief Returns true if the file of provided SourceLocation is the main - /// file. - bool isFromMainFile(SourceLocation Loc) const { + /// \brief Returns true if the spelling location for the given location + /// is in the main file buffer. + /// + /// This check ignores line marker directives. + bool isWrittenInMainFile(SourceLocation Loc) const { return getFileID(Loc) == getMainFileID(); } diff --git a/lib/Frontend/VerifyDiagnosticConsumer.cpp b/lib/Frontend/VerifyDiagnosticConsumer.cpp index efe6005ed7..f5555291a8 100644 --- a/lib/Frontend/VerifyDiagnosticConsumer.cpp +++ b/lib/Frontend/VerifyDiagnosticConsumer.cpp @@ -628,11 +628,11 @@ static bool IsFromSameFile(SourceManager &SM, SourceLocation DirectiveLoc, while (DiagnosticLoc.isMacroID()) DiagnosticLoc = SM.getImmediateMacroCallerLoc(DiagnosticLoc); - if (SM.isFromSameFile(DirectiveLoc, DiagnosticLoc)) + if (SM.isWrittenInSameFile(DirectiveLoc, DiagnosticLoc)) return true; const FileEntry *DiagFile = SM.getFileEntryForID(SM.getFileID(DiagnosticLoc)); - if (!DiagFile && SM.isFromMainFile(DirectiveLoc)) + if (!DiagFile && SM.isWrittenInMainFile(DirectiveLoc)) return true; return (DiagFile == SM.getFileEntryForID(SM.getFileID(DirectiveLoc))); diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index ef0cbd656f..86d6ad9eb8 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -2040,7 +2040,7 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, assert(!MI->isUsed()); // If we need warning for not using the macro, add its location in the // warn-because-unused-macro set. If it gets used it will be removed from set. - if (isInPrimaryFile() && // don't warn for include'd macros. + if (getSourceManager().isInMainFile(MI->getDefinitionLoc()) && Diags->getDiagnosticLevel(diag::pp_macro_not_used, MI->getDefinitionLoc()) != DiagnosticsEngine::Ignored) { MI->setIsWarnIfUnused(true); diff --git a/lib/Rewrite/Frontend/RewriteMacros.cpp b/lib/Rewrite/Frontend/RewriteMacros.cpp index 3c1d2e1190..4f6a93f7e0 100644 --- a/lib/Rewrite/Frontend/RewriteMacros.cpp +++ b/lib/Rewrite/Frontend/RewriteMacros.cpp @@ -115,7 +115,7 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, raw_ostream *OS) { SourceLocation PPLoc = SM.getExpansionLoc(PPTok.getLocation()); // If PPTok is from a different source file, ignore it. - if (!SM.isFromMainFile(PPLoc)) { + if (!SM.isWrittenInMainFile(PPLoc)) { PP.Lex(PPTok); continue; } diff --git a/lib/Rewrite/Frontend/RewriteModernObjC.cpp b/lib/Rewrite/Frontend/RewriteModernObjC.cpp index 546f9217ae..80b6b4110c 100644 --- a/lib/Rewrite/Frontend/RewriteModernObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteModernObjC.cpp @@ -791,7 +791,7 @@ void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) { } } // If we have a decl in the main file, see if we should rewrite it. - if (SM->isFromMainFile(Loc)) + if (SM->isWrittenInMainFile(Loc)) return HandleDeclInMainFile(D); } diff --git a/lib/Rewrite/Frontend/RewriteObjC.cpp b/lib/Rewrite/Frontend/RewriteObjC.cpp index 316009fc51..d265c51f5b 100644 --- a/lib/Rewrite/Frontend/RewriteObjC.cpp +++ b/lib/Rewrite/Frontend/RewriteObjC.cpp @@ -721,7 +721,7 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { } } // If we have a decl in the main file, see if we should rewrite it. - if (SM->isFromMainFile(Loc)) + if (SM->isWrittenInMainFile(Loc)) return HandleDeclInMainFile(D); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 26f26316d1..6cc596cec1 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -722,7 +722,7 @@ void Sema::ActOnEndOfTranslationUnit() { else { if (FD->getStorageClass() == SC_Static && !FD->isInlineSpecified() && - !SourceMgr.isFromMainFile( + !SourceMgr.isInMainFile( SourceMgr.getExpansionLoc(FD->getLocation()))) Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl) << DiagD->getDeclName(); @@ -743,7 +743,7 @@ void Sema::ActOnEndOfTranslationUnit() { if (DiagD->isReferenced()) { Diag(DiagD->getLocation(), diag::warn_unneeded_internal_decl) << /*variable*/1 << DiagD->getDeclName(); - } else if (getSourceManager().isFromMainFile(DiagD->getLocation())) { + } else if (SourceMgr.isInMainFile(DiagD->getLocation())) { // If the declaration is in a header which is included into multiple // TUs, it will declare one variable per TU, and one of the other // variables may be used. So, only warn if the declaration is in the diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 6fd3aa1fd4..5e0acc0787 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -6288,7 +6288,7 @@ void Sema::CheckArrayAccess(const Expr *BaseExpr, const Expr *IndexExpr, if (SourceMgr.isInSystemHeader(RBracketLoc)) { SourceLocation IndexLoc = SourceMgr.getSpellingLoc( IndexExpr->getLocStart()); - if (SourceMgr.isFromSameFile(RBracketLoc, IndexLoc)) + if (SourceMgr.isWrittenInSameFile(RBracketLoc, IndexLoc)) return; } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 528396d559..6ebfb57974 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6710,7 +6710,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, IdentLoc, Named, CommonAncestor); if (IsUsingDirectiveInToplevelContext(CurContext) && - !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { + !SourceMgr.isInMainFile(SourceMgr.getExpansionLoc(IdentLoc))) { Diag(IdentLoc, diag::warn_using_directive_in_header); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 2dbc82dc7a..1c5e24e278 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -229,7 +229,7 @@ static void diagnoseUseOfInternalDeclInInlineFunction(Sema &S, // This last can give us false negatives, but it's better than warning on // wrappers for simple C library functions. const FunctionDecl *UsedFn = dyn_cast(D); - bool DowngradeWarning = S.getSourceManager().isFromMainFile(Loc); + bool DowngradeWarning = S.getSourceManager().isInMainFile(Loc); if (!DowngradeWarning && UsedFn) DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr(); diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 2123a45181..1df3053edf 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2233,7 +2233,7 @@ static void removePunyEdges(PathPieces &path, SourceLocation FirstLoc = start->getLocStart(); SourceLocation SecondLoc = end->getLocStart(); - if (!SM.isFromSameFile(FirstLoc, SecondLoc)) + if (!SM.isWrittenInSameFile(FirstLoc, SecondLoc)) continue; if (SM.isBeforeInTranslationUnit(SecondLoc, FirstLoc)) std::swap(SecondLoc, FirstLoc); diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index 9ab6874756..59cdfbb7f9 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -741,7 +741,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, // TODO: It could actually be subclassed if the subclass is private as well. // This is probably very rare. SourceLocation InterfLoc = IDecl->getEndOfDefinitionLoc(); - if (InterfLoc.isValid() && SM.isFromMainFile(InterfLoc)) + if (InterfLoc.isValid() && SM.isInMainFile(InterfLoc)) return false; // Assume that property accessors are not overridden. @@ -763,7 +763,7 @@ bool ObjCMethodCall::canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, return false; // If outside the main file, - if (D->getLocation().isValid() && !SM.isFromMainFile(D->getLocation())) + if (D->getLocation().isValid() && !SM.isInMainFile(D->getLocation())) return true; if (D->isOverriding()) { diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 63dccff374..4fb6523944 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -764,7 +764,7 @@ static bool mayInlineDecl(const CallEvent &Call, AnalysisDeclContext *CalleeADC, // Conditionally control the inlining of methods on objects that look // like C++ containers. if (!Opts.mayInlineCXXContainerCtorsAndDtors()) - if (!Ctx.getSourceManager().isFromMainFile(FD->getLocation())) + if (!Ctx.getSourceManager().isInMainFile(FD->getLocation())) if (isContainerCtorOrDtor(Ctx, FD)) return false; diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 82d8f37105..5f26085cab 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -129,11 +129,11 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, if (CallLoc.isMacroID()) return 0; - assert(SMgr.isFromMainFile(CallLoc) && + assert(SMgr.isInMainFile(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())) + if (!SMgr.isInMainFile(CP->callEnterWithin.asLocation())) return CP; const PathPieces &Path = CP->path; diff --git a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index abc1e9fc52..9efe99767e 100644 --- a/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -596,7 +596,7 @@ AnalysisConsumer::getModeForDecl(Decl *D, AnalysisMode Mode) { // - System headers: don't run any checks. SourceManager &SM = Ctx->getSourceManager(); SourceLocation SL = SM.getExpansionLoc(D->getLocation()); - if (!Opts->AnalyzeAll && !SM.isFromMainFile(SL)) { + if (!Opts->AnalyzeAll && !SM.isInMainFile(SL)) { if (SL.isInvalid() || SM.isInSystemHeader(SL)) return AM_None; return Mode & ~AM_Path; diff --git a/test/Preprocessor/warn-macro-unused.c b/test/Preprocessor/warn-macro-unused.c index c33aeb5df9..a305cc9966 100644 --- a/test/Preprocessor/warn-macro-unused.c +++ b/test/Preprocessor/warn-macro-unused.c @@ -2,6 +2,10 @@ #include "warn-macro-unused.h" +# 1 "warn-macro-unused-fake-header.h" 1 +#define unused_from_fake_header +# 5 "warn-macro-unused.c" 2 + #define unused // expected-warning {{macro is not used}} #define unused unused diff --git a/test/Sema/inline.c b/test/Sema/inline.c index 496e282eca..8a3835b71a 100644 --- a/test/Sema/inline.c +++ b/test/Sema/inline.c @@ -83,6 +83,19 @@ extern inline void defineStaticVarInExtern() { static int y = 0; // ok } +// Check behavior of line markers. +# 1 "XXX.h" 1 +inline int useStaticMainFileInLineMarker() { // expected-note 2 {{use 'static' to give inline function 'useStaticMainFileInLineMarker' internal linkage}} + staticFunction(); // expected-warning{{static function 'staticFunction' is used in an inline function with external linkage}} + return staticVar; // expected-warning{{static variable 'staticVar' is used in an inline function with external linkage}} +} +# 100 "inline.c" 2 + +inline int useStaticMainFileAfterLineMarker() { + staticFunction(); // no-warning + return staticVar; // no-warning +} + #endif diff --git a/test/SemaCXX/warn-using-namespace-in-header.cpp b/test/SemaCXX/warn-using-namespace-in-header.cpp index f68b99893a..6b84e6e70a 100644 --- a/test/SemaCXX/warn-using-namespace-in-header.cpp +++ b/test/SemaCXX/warn-using-namespace-in-header.cpp @@ -57,4 +57,13 @@ using namespace dont_warn; // cc file. USING_MACRO +// Check behavior of line markers. +namespace warn_header_with_line_marker {} +# 1 "XXX.h" 1 +using namespace warn_header_with_line_marker; // expected-warning {{using namespace directive in global context in header}} +# 70 "warn-using-namespace-in-header.cpp" 2 + +namespace nowarn_after_line_marker {} +using namespace nowarn_after_line_marker; + #endif diff --git a/tools/libclang/CXSourceLocation.cpp b/tools/libclang/CXSourceLocation.cpp index 71e425d1f7..a33c9d4f26 100644 --- a/tools/libclang/CXSourceLocation.cpp +++ b/tools/libclang/CXSourceLocation.cpp @@ -217,7 +217,7 @@ int clang_Location_isFromMainFile(CXSourceLocation location) { const SourceManager &SM = *static_cast(location.ptr_data[0]); - return SM.isFromMainFile(Loc); + return SM.isWrittenInMainFile(Loc); } void clang_getExpansionLocation(CXSourceLocation location, -- 2.40.0