diff options
author | Douglas Gregor <dgregor@apple.com> | 2009-01-05 19:45:36 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2009-01-05 19:45:36 +0000 |
commit | 074149e11baf5f7db12f84efd5c34ba6e35d5cdf (patch) | |
tree | a02b3f87f914315d7ac21bc25fddf46250229d59 /lib/Sema/SemaDecl.cpp | |
parent | e1dccaefe2d44a9f83f8c3f087438a3297254cac (diff) |
Introduce support for "transparent" DeclContexts, which are
DeclContexts whose members are visible from enclosing DeclContexts up
to (and including) the innermost enclosing non-transparent
DeclContexts. Transparent DeclContexts unify the mechanism to be used
for various language features, including C enumerations, anonymous
unions, C++0x inline namespaces, and C++ linkage
specifications. Please refer to the documentation in the Clang
internals manual for more information.
Only enumerations and linkage specifications currently use transparent
DeclContexts.
Still to do: use transparent DeclContexts to implement anonymous
unions and GCC's anonymous structs extension, and, later, the C++0x
features. We also need to tighten up the DeclContext/ScopedDecl link
to ensure that every ScopedDecl is in a single DeclContext, which
will ensure that we can then enforce ownership and reduce the memory
footprint of DeclContext.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61735 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 21d3ad68a0..f4677f03f4 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -93,6 +93,13 @@ void Sema::PopDeclContext() { /// Add this decl to the scope shadowed decl chains. void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { + // Move up the scope chain until we find the nearest enclosing + // non-transparent context. The declaration will be introduced into this + // scope. + while (S->getEntity() && + ((DeclContext *)S->getEntity())->isTransparentContext()) + S = S->getParent(); + S->AddDecl(D); // Add scoped declarations into their context, so that they can be @@ -149,8 +156,11 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // We are pushing the name of a function, which might be an // overloaded name. FunctionDecl *FD = cast<FunctionDecl>(D); + DeclContext *DC = FD->getDeclContext(); + while (DC->isTransparentContext()) + DC = DC->getParent(); IdentifierResolver::iterator Redecl - = std::find_if(IdResolver.begin(FD->getDeclName(), CurContext, + = std::find_if(IdResolver.begin(FD->getDeclName(), DC, false/*LookInParentCtx*/), IdResolver.end(), std::bind1st(std::mem_fun(&ScopedDecl::declarationReplaces), @@ -337,7 +347,7 @@ Decl *Sema::LookupDecl(DeclarationName Name, unsigned NSI, Scope *S, Ctx = Ctx->getParent(); } - if (!LookInParent) + if (!LookInParent && !Ctx->isTransparentContext()) return 0; } } @@ -3117,6 +3127,15 @@ void Sema::ActOnFields(Scope* S, ProcessDeclAttributeList(Record, Attr); } +void Sema::ActOnEnumStartDefinition(Scope *S, DeclTy *EnumD) { + EnumDecl *Enum = cast_or_null<EnumDecl>((Decl *)EnumD); + + if (Enum) { + // Enter the enumeration context. + PushDeclContext(S, Enum); + } +} + Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, DeclTy *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, @@ -3212,20 +3231,22 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl, void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, DeclTy **Elements, unsigned NumElements) { EnumDecl *Enum = cast<EnumDecl>(static_cast<Decl*>(EnumDeclX)); + QualType EnumType = Context.getTypeDeclType(Enum); - if (Enum) { - if (EnumDecl *Def = cast_or_null<EnumDecl>(Enum->getDefinition(Context))) { - // Diagnose code like: - // enum e0 { - // E0 = sizeof(enum e0 { E1 }) - // }; - Diag(Def->getLocation(), diag::err_nested_redefinition) - << Enum->getDeclName(); - Diag(Enum->getLocation(), diag::note_previous_definition); - Enum->setInvalidDecl(); - return; - } + if (EnumType->getAsEnumType()->getDecl()->isDefinition()) { + EnumDecl *Def = EnumType->getAsEnumType()->getDecl(); + // Diagnose code like: + // enum e0 { + // E0 = sizeof(enum e0 { E1 }) + // }; + Diag(Def->getLocation(), diag::err_nested_redefinition) + << Enum->getDeclName(); + Diag(Enum->getLocation(), diag::note_previous_definition); + Enum->setInvalidDecl(); + PopDeclContext(); + return; } + // TODO: If the result value doesn't fit in an int, it must be a long or long // long value. ISO C does not support this, but GCC does as an extension, // emit a warning. @@ -3239,7 +3260,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, // Keep track of whether all elements have type int. bool AllElementsInt = true; - QualType EnumType = Context.getTypeDeclType(Enum); EnumConstantDecl *EltList = 0; for (unsigned i = 0; i != NumElements; ++i) { EnumConstantDecl *ECD = @@ -3392,6 +3412,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, DeclTy *EnumDeclX, Enum->completeDefinition(Context, BestType); Consumer.HandleTagDeclDefinition(Enum); + + // Leave the context of the enumeration. + PopDeclContext(); } Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, |