<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>