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/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp
index 027beed..18e78a0 100644
--- a/lib/Sema/IdentifierResolver.cpp
+++ b/lib/Sema/IdentifierResolver.cpp
@@ -60,6 +60,9 @@
   else
     return TUCtx();
 
+  while (Ctx->isTransparentContext())
+    Ctx = Ctx->getParent();
+
   if (isa<TranslationUnitDecl>(Ctx))
     return TUCtx();
 
@@ -83,30 +86,12 @@
 // IdDeclInfo Implementation
 //===----------------------------------------------------------------------===//
 
-/// FindContext - Returns an iterator pointing just after the decl that is
-/// in the given context or in a parent of it. The search is in reverse
-/// order, from end to begin.
-IdentifierResolver::IdDeclInfo::DeclsTy::iterator
-IdentifierResolver::IdDeclInfo::FindDeclVisibleInContext(
-                                            const LookupContext &Ctx,
-                                            const DeclsTy::iterator &Start) {
-  for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
-    if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
-      return I;
-  }
-
-  return Decls.begin();
-}
-
 /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
 /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
 /// be already added to the scope chain and must be in the same context as
 /// the decl that we want to add.
 void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D,
                                                  NamedDecl *Shadow) {
-  assert(LookupContext(D) == LookupContext(Shadow) &&
-    "Decl and Shadow not in same context!");
-
   for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
     if (Shadow == *(I-1)) {
       Decls.insert(I-1, D);
@@ -147,7 +132,15 @@
 /// true if 'D' belongs to the given declaration context.
 bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
                                        ASTContext &Context, Scope *S) const {
+  while (Ctx->isTransparentContext())
+    Ctx = Ctx->getParent();
+
   if (Ctx->isFunctionOrMethod()) {
+    // Ignore the scopes associated within transparent declaration contexts.
+    while (S->getEntity() && 
+           ((DeclContext *)S->getEntity())->isTransparentContext())
+      S = S->getParent();
+
     if (S->isDeclScope(D))
       return true;
     if (LangOpt.CPlusPlus) {
@@ -201,7 +194,6 @@
 /// encountered before the 'D' decl.
 void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
   assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
-  assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
 
   DeclarationName Name = D->getDeclName();
   void *Ptr = Name.getFETokenInfo<void>();
@@ -252,30 +244,14 @@
   void *Ptr = Name.getFETokenInfo<void>();
   if (!Ptr) return end();
 
-  LookupContext LC(Ctx);
-
   if (isDeclPtr(Ptr)) {
     NamedDecl *D = static_cast<NamedDecl*>(Ptr);
-    LookupContext DC(D);
-
-    if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
-        (!LookInParentCtx && LC == DC))
-      return iterator(D);
-    else
-      return end();
+    return iterator(D);
   }
 
   IdDeclInfo *IDI = toIdDeclInfo(Ptr);
 
-  IdDeclInfo::DeclsTy::iterator I;
-  if (LookInParentCtx)
-    I = IDI->FindDeclVisibleInContext(LC);
-  else {
-    for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
-      if (LookupContext(*(I-1)) == LC)
-        break;
-  }
-
+  IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
   if (I != IDI->decls_begin())
     return iterator(I-1, LookInParentCtx);
   else // No decls found.
@@ -285,22 +261,11 @@
 /// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
 void IdentifierResolver::iterator::PreIncIter() {
   NamedDecl *D = **this;
-  LookupContext Ctx(D);
   void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
   assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
   IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
 
   BaseIter I = getIterator();
-  if (LookInParentCtx())
-    I = Info->FindDeclVisibleInContext(Ctx, I);
-  else {
-    if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
-      // The next decl is in different declaration context.
-      // Skip remaining decls and set the iterator to the end.
-      I = Info->decls_begin();
-    }
-  }
-
   if (I != Info->decls_begin())
     *this = iterator(I-1, LookInParentCtx());
   else // No more decls.
diff --git a/lib/Sema/IdentifierResolver.h b/lib/Sema/IdentifierResolver.h
index 30846dc..3dab1b5 100644
--- a/lib/Sema/IdentifierResolver.h
+++ b/lib/Sema/IdentifierResolver.h
@@ -91,22 +91,7 @@
     inline DeclsTy::iterator decls_begin() { return Decls.begin(); }
     inline DeclsTy::iterator decls_end() { return Decls.end(); }
 
-    /// FindContext - Returns an iterator pointing just after the decl that is
-    /// in the given context or in a parent of it. The search is in reverse
-    /// order, from end to begin.
-    DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx) {
-      return FindDeclVisibleInContext(Ctx, Decls.end());
-    }
-
-    /// FindContext - Returns an iterator pointing just after the decl that is
-    /// in the given context or in a parent of it. The search is in reverse
-    /// order, from end to begin.
-    DeclsTy::iterator FindDeclVisibleInContext(const LookupContext &Ctx,
-                                  const DeclsTy::iterator &Start);
-
-    void AddDecl(NamedDecl *D) {
-      Decls.insert(FindDeclVisibleInContext(LookupContext(D)), D);
-    }
+    void AddDecl(NamedDecl *D) { Decls.push_back(D); }
 
     /// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
     /// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ca15176..d3f373f 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -288,12 +288,6 @@
   virtual void ObjCActOnStartOfMethodDef(Scope *S, DeclTy *D);
   
   virtual DeclTy *ActOnFinishFunctionBody(DeclTy *Decl, StmtArg Body);
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, SourceLocation LBrace,
-                                   SourceLocation RBrace, const char *Lang,
-                                   unsigned StrSize, 
-                                   DeclTy **Decls, unsigned NumDecls);
-  virtual DeclTy *ActOnLinkageSpec(SourceLocation Loc, const char *Lang,
-                                   unsigned StrSize, DeclTy *D);
   virtual DeclTy *ActOnFileScopeAsmDecl(SourceLocation Loc, ExprArg expr);
 
   /// Scope actions.
@@ -326,6 +320,7 @@
                            DeclTy **Fields, unsigned NumFields,
                            SourceLocation LBrac, SourceLocation RBrac,
                            AttributeList *AttrList);
+  virtual void ActOnEnumStartDefinition(Scope *S, DeclTy *EnumDecl);
   virtual DeclTy *ActOnEnumConstant(Scope *S, DeclTy *EnumDecl,
                                     DeclTy *LastEnumConstant,
                                     SourceLocation IdLoc, IdentifierInfo *Id,
@@ -980,6 +975,20 @@
                                                  SourceLocation RParenLoc);
 
   //===--------------------------------------------------------------------===//
+  // C++ Declarations
+  //
+  virtual DeclTy *ActOnStartLinkageSpecification(Scope *S,
+                                                 SourceLocation ExternLoc,
+                                                 SourceLocation LangLoc,
+                                                 const char *Lang,
+                                                 unsigned StrSize,
+                                                 SourceLocation LBraceLoc);
+  virtual DeclTy *ActOnFinishLinkageSpecification(Scope *S,
+                                                  DeclTy *LinkageSpec,
+                                                  SourceLocation RBraceLoc);
+
+
+  //===--------------------------------------------------------------------===//
   // C++ Classes
   //
   virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S,
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,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index e3c8373..7c05f6b 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2003,48 +2003,49 @@
   return false;
 }
 
-/// ActOnLinkageSpec - Parsed a C++ linkage-specification that
-/// contained braces. Lang/StrSize contains the language string that
-/// was parsed at location Loc. Decls/NumDecls provides the
-/// declarations parsed inside the linkage specification.
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
-                                     SourceLocation LBrace,
-                                     SourceLocation RBrace,
-                                     const char *Lang,
-                                     unsigned StrSize,
-                                     DeclTy **Decls, unsigned NumDecls) {
+/// ActOnStartLinkageSpecification - Parsed the beginning of a C++
+/// linkage specification, including the language and (if present)
+/// the '{'. ExternLoc is the location of the 'extern', LangLoc is
+/// the location of the language string literal, which is provided
+/// by Lang/StrSize. LBraceLoc, if valid, provides the location of
+/// the '{' brace. Otherwise, this linkage specification does not
+/// have any braces.
+Sema::DeclTy *Sema::ActOnStartLinkageSpecification(Scope *S,
+                                                   SourceLocation ExternLoc,
+                                                   SourceLocation LangLoc,
+                                                   const char *Lang,
+                                                   unsigned StrSize,
+                                                   SourceLocation LBraceLoc) {
   LinkageSpecDecl::LanguageIDs Language;
   if (strncmp(Lang, "\"C\"", StrSize) == 0)
     Language = LinkageSpecDecl::lang_c;
   else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
     Language = LinkageSpecDecl::lang_cxx;
   else {
-    Diag(Loc, diag::err_bad_language);
+    Diag(LangLoc, diag::err_bad_language);
     return 0;
   }
   
   // FIXME: Add all the various semantics of linkage specifications
   
-  return LinkageSpecDecl::Create(Context, Loc, Language, 
-                                 (Decl **)Decls, NumDecls);
+  LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
+                                               LangLoc, Language, 
+                                               LBraceLoc.isValid());
+  CurContext->addDecl(Context, D);
+  PushDeclContext(S, D);
+  return D;
 }
 
-Sema::DeclTy *Sema::ActOnLinkageSpec(SourceLocation Loc,
-                                     const char *Lang, unsigned StrSize,
-                                     DeclTy *D) {
-  LinkageSpecDecl::LanguageIDs Language;
-  Decl *dcl = static_cast<Decl *>(D);
-  if (strncmp(Lang, "\"C\"", StrSize) == 0)
-    Language = LinkageSpecDecl::lang_c;
-  else if (strncmp(Lang, "\"C++\"", StrSize) == 0)
-    Language = LinkageSpecDecl::lang_cxx;
-  else {
-    Diag(Loc, diag::err_bad_language);
-    return 0;
-  }
-  
-  // FIXME: Add all the various semantics of linkage specifications
-  return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
+/// ActOnFinishLinkageSpecification - Completely the definition of
+/// the C++ linkage specification LinkageSpec. If RBraceLoc is
+/// valid, it's the position of the closing '}' brace in a linkage
+/// specification that uses braces.
+Sema::DeclTy *Sema::ActOnFinishLinkageSpecification(Scope *S,
+                                                    DeclTy *LinkageSpec,
+                                                    SourceLocation RBraceLoc) {
+  if (LinkageSpec)
+    PopDeclContext();
+  return LinkageSpec;
 }
 
 /// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch