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
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 21d3ad6..f4677f0 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -93,6 +93,13 @@
 
 /// 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 @@
     // 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 @@
         Ctx = Ctx->getParent();
       }
       
-      if (!LookInParent)
+      if (!LookInParent && !Ctx->isTransparentContext())
         return 0;
     }
   }
@@ -3117,6 +3127,15 @@
     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 @@
 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 @@
   // 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 @@
   
   Enum->completeDefinition(Context, BestType);
   Consumer.HandleTagDeclDefinition(Enum);
+
+  // Leave the context of the enumeration.
+  PopDeclContext();
 }
 
 Sema::DeclTy *Sema::ActOnFileScopeAsmDecl(SourceLocation Loc,