[PATCH] Correctly check for the main file in the presence of line markers

Eli Friedman eli.friedman at gmail.com
Mon Jul 29 18:33:20 PDT 2013


Patch attached.  Basically, the idea is that even if a SourceLocation
is technically in the main file, we might want to treat it differently
in the presence of line markers.  I added
SourceManager::isPresumedFromMainFile to check this.

I'm particularly looking for suggestions about the name of the method;
having isFromMainFile and isPresumedFromMainFile seems very confusing,
but I don't really have any better ideas.

-Eli
-------------- next part --------------
diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h
index 9fc4885..b55d662 100644
--- a/include/clang/Basic/SourceManager.h
+++ b/include/clang/Basic/SourceManager.h
@@ -1292,6 +1292,17 @@ public:
   PresumedLoc getPresumedLoc(SourceLocation Loc,
                              bool UseLineDirectives = true) const;
 
+  /// \brief Returns whether the PresumedLoc for a given SourceLocation is 
+  /// from a #include directive.
+  ///
+  /// 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 isFromMainFile() because it takes line marker directives into
+  // account.
+  bool isPresumedFromMainFile(SourceLocation Loc) const {
+    return getPresumedLoc(Loc).getIncludeLoc().isInvalid();
+  }
+
   /// \brief Returns true if both SourceLocations correspond to the same file.
   bool isFromSameFile(SourceLocation Loc1, SourceLocation Loc2) const {
     return getFileID(Loc1) == getFileID(Loc2);
diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp
index c70019f..45a3fc0 100644
--- a/lib/Lex/PPDirectives.cpp
+++ b/lib/Lex/PPDirectives.cpp
@@ -2037,7 +2037,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().isPresumedFromMainFile(MI->getDefinitionLoc()) &&
       Diags->getDiagnosticLevel(diag::pp_macro_not_used,
           MI->getDefinitionLoc()) != DiagnosticsEngine::Ignored) {
     MI->setIsWarnIfUnused(true);
diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp
index 324bbd2..81500e8 100644
--- a/lib/Lex/Pragma.cpp
+++ b/lib/Lex/Pragma.cpp
@@ -349,7 +349,7 @@ void Preprocessor::HandleMicrosoft__pragma(Token &Tok) {
 /// HandlePragmaOnce - Handle \#pragma once.  OnceTok is the 'once'.
 ///
 void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
-  if (isInPrimaryFile()) {
+  if (getSourceManager().isPresumedFromMainFile(OnceTok.getLocation())) {
     Diag(OnceTok, diag::pp_pragma_once_in_main_file);
     return;
   }
@@ -413,7 +413,7 @@ void Preprocessor::HandlePragmaPoison(Token &PoisonTok) {
 /// HandlePragmaSystemHeader - Implement \#pragma GCC system_header.  We know
 /// that the whole directive has been parsed.
 void Preprocessor::HandlePragmaSystemHeader(Token &SysHeaderTok) {
-  if (isInPrimaryFile()) {
+  if (getSourceManager().isPresumedFromMainFile(SysHeaderTok.getLocation())) {
     Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
     return;
   }
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 8faa919..034db95 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -721,7 +721,7 @@ void Sema::ActOnEndOfTranslationUnit() {
           else {
             if (FD->getStorageClass() == SC_Static &&
                 !FD->isInlineSpecified() &&
-                !SourceMgr.isFromMainFile(
+                !SourceMgr.isPresumedFromMainFile(
                    SourceMgr.getExpansionLoc(FD->getLocation())))
               Diag(DiagD->getLocation(), diag::warn_unneeded_static_internal_decl)
                 << DiagD->getDeclName();
@@ -742,7 +742,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.isPresumedFromMainFile(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/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 3df0472..9af8a8e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -6717,7 +6717,8 @@ Decl *Sema::ActOnUsingDirective(Scope *S,
                                       IdentLoc, Named, CommonAncestor);
 
     if (IsUsingDirectiveInToplevelContext(CurContext) &&
-        !SourceMgr.isFromMainFile(SourceMgr.getExpansionLoc(IdentLoc))) {
+        !SourceMgr.isPresumedFromMainFile(
+            SourceMgr.getExpansionLoc(IdentLoc))) {
       Diag(IdentLoc, diag::warn_using_directive_in_header);
     }
 
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 5b0029a..246e8f5 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<FunctionDecl>(D);
-  bool DowngradeWarning = S.getSourceManager().isFromMainFile(Loc);
+  bool DowngradeWarning = S.getSourceManager().isPresumedFromMainFile(Loc);
   if (!DowngradeWarning && UsedFn)
     DowngradeWarning = UsedFn->isInlined() || UsedFn->hasAttr<ConstAttr>();
 
diff --git a/test/Preprocessor/warn-macro-unused.c b/test/Preprocessor/warn-macro-unused.c
index c33aeb5..a305cc9 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


More information about the cfe-commits mailing list