r257403 - When a tag is declared in prototype scope in C, if we've decided that it

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 11 14:41:53 PST 2016


Author: rsmith
Date: Mon Jan 11 16:41:53 2016
New Revision: 257403

URL: http://llvm.org/viewvc/llvm-project?rev=257403&view=rev
Log:
When a tag is declared in prototype scope in C, if we've decided that it
redeclares an existing tag but are creating a new declaration anyway (because
it has attributes or changes the visibility of the name), don't warn that it
won't be visible outside the current scope. That's not true.

Also narrow down the set of cases where we create these extra declarations when
building modules; previously, all tag declarations but the first in a module
header would get this treatment if -fmodules-local-submodule-visibility. (This
isn't a functional change, but we try to avoid creating these extra
declarations whenever we can.)

Added:
    cfe/trunk/test/Modules/tag-injection.c
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Sema/decl-in-prototype.c

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=257403&r1=257402&r2=257403&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan 11 16:41:53 2016
@@ -12316,7 +12316,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
             } else if (TUK == TUK_Reference &&
                        (PrevTagDecl->getFriendObjectKind() ==
                             Decl::FOK_Undeclared ||
-                        getOwningModule(PrevDecl) !=
+                        PP.getModuleContainingLocation(
+                            PrevDecl->getLocation()) !=
                             PP.getModuleContainingLocation(KWLoc)) &&
                        SS.isEmpty()) {
               // This declaration is a reference to an existing entity, but
@@ -12326,8 +12327,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned
               // the declaration would have meant the same thing if no prior
               // declaration were found, that is, if it was found in the same
               // scope where we would have injected a declaration.
-              if (!getTagInjectionContext(CurContext)
-                       ->getRedeclContext()
+              if (!getTagInjectionContext(CurContext)->getRedeclContext()
                        ->Equals(PrevDecl->getDeclContext()->getRedeclContext()))
                 return PrevTagDecl;
               // This is in the injected scope, create a new declaration in
@@ -12634,7 +12634,7 @@ CreateNewDecl:
             << Name;
         Invalid = true;
       }
-    } else {
+    } else if (!PrevDecl) {
       Diag(Loc, diag::warn_decl_in_param_list) << Context.getTagDeclType(New);
     }
     DeclsInPrototypeScope.push_back(New);

Added: cfe/trunk/test/Modules/tag-injection.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/tag-injection.c?rev=257403&view=auto
==============================================================================
--- cfe/trunk/test/Modules/tag-injection.c (added)
+++ cfe/trunk/test/Modules/tag-injection.c Mon Jan 11 16:41:53 2016
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo 'struct a;' > %t/a.h
+// RUN: echo 'struct b {}; void foo(struct b*);' > %t/b.h
+// RUN: echo 'module X { module a { header "a.h" } module b { header "b.h" } }' > %t/x.modulemap
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fmodule-map-file=%t/x.modulemap %s -I%t -verify
+
+#include "a.h"
+
+void f(struct a *p);
+
+// FIXME: We should warn that 'b' will not be visible outside of this function,
+// but we merge this 'b' with X.b's 'b' because we don't yet implement C's
+// "compatible types" rule.
+void g(struct b *p);
+
+struct b b; // expected-error {{definition of 'b' must be imported from module 'X.b' before it is required}}
+// expected-note at b.h:1 {{here}}

Modified: cfe/trunk/test/Sema/decl-in-prototype.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/decl-in-prototype.c?rev=257403&r1=257402&r2=257403&view=diff
==============================================================================
--- cfe/trunk/test/Sema/decl-in-prototype.c (original)
+++ cfe/trunk/test/Sema/decl-in-prototype.c Mon Jan 11 16:41:53 2016
@@ -35,3 +35,6 @@ void f6(struct z {int b;} c) { // expect
 void pr19018_1 (enum e19018 { qq } x); // expected-warning{{declaration of 'enum e19018' will not be visible outside of this function}}
 enum e19018 qq; //expected-error{{tentative definition has type 'enum e19018' that is never completed}} \
                 //expected-note{{forward declaration of 'enum e19018'}}
+
+// Only warn once, even if we create two declarations.
+void f(struct q *, struct __attribute__((aligned(4))) q *); // expected-warning {{will not be visible outside}}




More information about the cfe-commits mailing list