<div dir="ltr">Thanks. But a few C headers are complaining. Investigating.<div><br></div><div><a href="http://lab.llvm.org:8011/builders/clang-x86_64-linux-selfhost-modules/builds/10380">http://lab.llvm.org:8011/builders/clang-x86_64-linux-selfhost-modules/builds/10380</a><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Sat, Jan 9, 2016 at 4:02 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Sat Jan  9 00:58:48 2016<br>
New Revision: 257251<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=257251&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=257251&view=rev</a><br>
Log:<br>
[modules] If we're treating an elaborated-type-specifier as if it introduces a<br>
tag (because the previous declaration was found in a different module), inject<br>
the tag into the appropriate scope (that is, the enclosing scope if we're in a<br>
function prototype scope in C++).<br>
<br>
Modified:<br>
    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
    cfe/trunk/test/Modules/tag-injection.cpp<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=257251&r1=257250&r2=257251&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=257251&r1=257250&r2=257251&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Jan  9 00:58:48 2016<br>
@@ -11798,6 +11798,28 @@ static bool isAcceptableTagRedeclContext<br>
   return false;<br>
 }<br>
<br>
+/// Find the DeclContext in which a tag is implicitly declared if we see an<br>
+/// elaborated type specifier in the specified context, and lookup finds<br>
+/// nothing.<br>
+static DeclContext *getTagInjectionContext(DeclContext *DC) {<br>
+  while (!DC->isFileContext() && !DC->isFunctionOrMethod())<br>
+    DC = DC->getParent();<br>
+  return DC;<br>
+}<br>
+<br>
+/// Find the Scope in which a tag is implicitly declared if we see an<br>
+/// elaborated type specifier in the specified context, and lookup finds<br>
+/// nothing.<br>
+static Scope *getTagInjectionScope(Scope *S, const LangOptions &LangOpts) {<br>
+  while (S->isClassScope() ||<br>
+         (LangOpts.CPlusPlus &&<br>
+          S->isFunctionPrototypeScope()) ||<br>
+         ((S->getFlags() & Scope::DeclScope) == 0) ||<br>
+         (S->getEntity() && S->getEntity()->isTransparentContext()))<br>
+    S = S->getParent();<br>
+  return S;<br>
+}<br>
+<br>
 /// \brief This is invoked when we see 'struct foo' or 'struct {'.  In the<br>
 /// former case, Name will be non-null.  In the later case, Name will be null.<br>
 /// TagSpec indicates what kind of tag this is. TUK indicates whether this is a<br>
@@ -12114,16 +12136,10 @@ Decl *Sema::ActOnTag(Scope *S, unsigned<br>
       // Find the context where we'll be declaring the tag.<br>
       // FIXME: We would like to maintain the current DeclContext as the<br>
       // lexical context,<br>
-      while (!SearchDC->isFileContext() && !SearchDC->isFunctionOrMethod())<br>
-        SearchDC = SearchDC->getParent();<br>
+      SearchDC = getTagInjectionContext(SearchDC);<br>
<br>
       // Find the scope where we'll be declaring the tag.<br>
-      while (S->isClassScope() ||<br>
-             (getLangOpts().CPlusPlus &&<br>
-              S->isFunctionPrototypeScope()) ||<br>
-             ((S->getFlags() & Scope::DeclScope) == 0) ||<br>
-             (S->getEntity() && S->getEntity()->isTransparentContext()))<br>
-        S = S->getParent();<br>
+      S = getTagInjectionScope(S, getLangOpts());<br>
     } else {<br>
       assert(TUK == TUK_Friend);<br>
       // C++ [namespace.memdef]p3:<br>
@@ -12293,14 +12309,13 @@ Decl *Sema::ActOnTag(Scope *S, unsigned<br>
               // the declaration would have meant the same thing if no prior<br>
               // declaration were found, that is, if it was found in the same<br>
               // scope where we would have injected a declaration.<br>
-              DeclContext *InjectedDC = CurContext;<br>
-              while (!InjectedDC->isFileContext() &&<br>
-                     !InjectedDC->isFunctionOrMethod())<br>
-                InjectedDC = InjectedDC->getParent();<br>
-              if (!InjectedDC->getRedeclContext()->Equals(<br>
-                  PrevDecl->getDeclContext()->getRedeclContext()))<br>
+              if (!getTagInjectionContext(CurContext)<br>
+                       ->getRedeclContext()<br>
+                       ->Equals(PrevDecl->getDeclContext()->getRedeclContext()))<br>
                 return PrevTagDecl;<br>
-              // This is in the injected scope, create a new declaration.<br>
+              // This is in the injected scope, create a new declaration in<br>
+              // that scope.<br>
+              S = getTagInjectionScope(S, getLangOpts());<br>
             } else {<br>
               return PrevTagDecl;<br>
             }<br>
<br>
Modified: cfe/trunk/test/Modules/tag-injection.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/tag-injection.cpp?rev=257251&r1=257250&r2=257251&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/tag-injection.cpp?rev=257251&r1=257250&r2=257251&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/tag-injection.cpp (original)<br>
+++ cfe/trunk/test/Modules/tag-injection.cpp Sat Jan  9 00:58:48 2016<br>
@@ -1,12 +1,15 @@<br>
 // RUN: rm -rf %t<br>
 // RUN: mkdir %t<br>
-// RUN: touch %t/a.h<br>
-// RUN: echo 'struct X {};' > %t/b.h<br>
+// RUN: echo 'struct tm;' > %t/a.h<br>
+// RUN: echo 'struct X {}; void foo(struct tm*);' > %t/b.h<br>
 // RUN: echo 'module X { module a { header "a.h" } module b { header "b.h" } }' > %t/x.modulemap<br>
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x c++ -fmodule-map-file=%t/x.modulemap %s -I%t -verify -std=c++11<br>
 // RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -x c++ -fmodule-map-file=%t/x.modulemap %s -I%t -verify -fmodules-local-submodule-visibility -std=c++11<br>
<br>
 #include "a.h"<br>
<br>
+using ::tm;<br>
+<br>
 struct A {<br>
   // This use of 'struct X' makes the declaration (but not definition) of X visible.<br>
   virtual void f(struct X *p);<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>