aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-12 18:45:55 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-12 18:45:55 +0000
commit1a0d31a3d7f14ddc6370ba912c778aece6c12cf0 (patch)
tree50d74e3ec8f55a33c99d18b782cb60412444bc08 /lib/Sema/SemaDecl.cpp
parent816dd50947cd4c43814fab0b904afcb7c94f15d4 (diff)
Properly set the scope of non-fields declared within a struct, union,
or enum to be outside that struct, union, or enum. Fixes several regressions: <rdar://problem/6487662> <rdar://problem/6487669> <rdar://problem/6487684> <rdar://problem/6487702> PR clang/3305 PR clang/3312 There is still some work to do in Objective-C++, but this requires that each of the Objective-C entities (interfaces, implementations, etc.) to be introduced into the context stack with PushDeclContext/PopDeclContext. This will be a separate fix, later. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62091 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r--lib/Sema/SemaDecl.cpp44
1 files changed, 37 insertions, 7 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a67049cf14..f3f0a08bee 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -251,6 +251,38 @@ MaybeConstructOverloadSet(ASTContext &Context,
return *I;
}
+/// getNonFieldDeclScope - Retrieves the innermost scope, starting
+/// from S, where a non-field would be declared. This routine copes
+/// with the difference between C and C++ scoping rules in structs and
+/// unions. For example, the following code is well-formed in C but
+/// ill-formed in C++:
+/// @code
+/// struct S6 {
+/// enum { BAR } e;
+/// };
+///
+/// void test_S6() {
+/// struct S6 a;
+/// a.e = BAR;
+/// }
+/// @endcode
+/// For the declaration of BAR, this routine will return a different
+/// scope. The scope S will be the scope of the unnamed enumeration
+/// within S6. In C++, this routine will return the scope associated
+/// with S6, because the enumeration's scope is a transparent
+/// context but structures can contain non-field names. In C, this
+/// routine will return the translation unit scope, since the
+/// enumeration's scope is a transparent context and structures cannot
+/// contain non-field names.
+Scope *Sema::getNonFieldDeclScope(Scope *S) {
+ while (((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext()) ||
+ (S->isClassScope() && !getLangOptions().CPlusPlus))
+ S = S->getParent();
+ return S;
+}
+
/// LookupDecl - Look up the inner-most declaration in the specified
/// namespace. NamespaceNameOnly - during lookup only namespace names
/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
@@ -2999,7 +3031,9 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagType, TagKind TK,
// Find the scope where we'll be declaring the tag.
while (S->isClassScope() ||
(getLangOptions().CPlusPlus && S->isFunctionPrototypeScope()) ||
- ((S->getFlags() & Scope::DeclScope) == 0))
+ ((S->getFlags() & Scope::DeclScope) == 0) ||
+ (S->getEntity() &&
+ ((DeclContext *)S->getEntity())->isTransparentContext()))
S = S->getParent();
}
@@ -3065,10 +3099,7 @@ CreateNewDecl:
// If this has an identifier, add it to the scope stack.
if (Name) {
- // The scope passed in may not be a decl scope. Zip up the scope tree until
- // we find one that is.
- while ((S->getFlags() & Scope::DeclScope) == 0)
- S = S->getParent();
+ S = getNonFieldDeclScope(S);
// Add it to the decl chain.
if (LexicalContext != CurContext) {
@@ -3509,8 +3540,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
// The scope passed in may not be a decl scope. Zip up the scope tree until
// we find one that is.
- while ((S->getFlags() & Scope::DeclScope) == 0)
- S = S->getParent();
+ S = getNonFieldDeclScope(S);
// Verify that there isn't already something declared with this name in this
// scope.