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