aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-01-05 19:45:36 +0000
committerDouglas Gregor <dgregor@apple.com>2009-01-05 19:45:36 +0000
commit074149e11baf5f7db12f84efd5c34ba6e35d5cdf (patch)
treea02b3f87f914315d7ac21bc25fddf46250229d59 /lib/Sema/SemaDecl.cpp
parente1dccaefe2d44a9f83f8c3f087438a3297254cac (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.cpp53
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,