diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-01-12 18:45:55 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-01-12 18:45:55 +0000 |
commit | 1a0d31a3d7f14ddc6370ba912c778aece6c12cf0 (patch) | |
tree | 50d74e3ec8f55a33c99d18b782cb60412444bc08 /lib/Sema/SemaDecl.cpp | |
parent | 816dd50947cd4c43814fab0b904afcb7c94f15d4 (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.cpp | 44 |
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. |