summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-01-09 06:58:48 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-01-09 06:58:48 +0000
commite123cd2f403f65ae79eb736b2141931aa65c2861 (patch)
tree34c49fc0ee9b9dcdb509a035bc52b4f28488b4b2 /clang/lib/Sema
parent734e73342de24e74ff8705703f644d2ca66a8db2 (diff)
downloadbcm5719-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/Sema')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp45
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;
}
OpenPOWER on IntegriCloud