diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-01-09 06:58:48 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2016-01-09 06:58:48 +0000 |
commit | e123cd2f403f65ae79eb736b2141931aa65c2861 (patch) | |
tree | 34c49fc0ee9b9dcdb509a035bc52b4f28488b4b2 /clang/lib | |
parent | 734e73342de24e74ff8705703f644d2ca66a8db2 (diff) | |
download | bcm5719-llvm-e123cd2f403f65ae79eb736b2141931aa65c2861.tar.gz bcm5719-llvm-e123cd2f403f65ae79eb736b2141931aa65c2861.zip |
[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++).
llvm-svn: 257251
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 45 |
1 files changed, 30 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 645074deaa0..0864984c063 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11798,6 +11798,28 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, 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 TagSpec, TagUseKind TUK, // 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 TagSpec, TagUseKind TUK, // 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; } |