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/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c6b3c53..59d8a07 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -406,10 +406,24 @@
   }
 }
 
+bool DeclContext::isTransparentContext() const {
+  if (DeclKind == Decl::Enum)
+    return true; // FIXME: Check for C++0x scoped enums
+  else if (DeclKind == Decl::LinkageSpec)
+    return true;
+  else if (DeclKind == Decl::Record || DeclKind == Decl::CXXRecord)
+    return false; // FIXME: need to know about anonymous unions/structs
+  else if (DeclKind == Decl::Namespace)
+    return false; // FIXME: Check for C++0x inline namespaces
+
+  return false;
+}
+
 DeclContext *DeclContext::getPrimaryContext(ASTContext &Context) {
   switch (DeclKind) {
-  case Decl::Block:
   case Decl::TranslationUnit:
+  case Decl::LinkageSpec:
+  case Decl::Block:    
     // There is only one DeclContext for these entities.
     return this;
 
@@ -418,10 +432,15 @@
     return static_cast<NamespaceDecl*>(this)->getOriginalNamespace();
 
   case Decl::Enum:
+#if 0
+    // FIXME: See the comment for CXXRecord, below.
     // The declaration associated with the enumeration type is our
     // primary context.
     return Context.getTypeDeclType(static_cast<EnumDecl*>(this))
              ->getAsEnumType()->getDecl();
+#else
+    return this;
+#endif
 
   case Decl::Record:
   case Decl::CXXRecord: {
@@ -461,13 +480,14 @@
 
 DeclContext *DeclContext::getNextContext() {
   switch (DeclKind) {
-  case Decl::Block:
   case Decl::TranslationUnit:
   case Decl::Enum:
   case Decl::Record:
   case Decl::CXXRecord:
   case Decl::ObjCMethod:
   case Decl::ObjCInterface:
+  case Decl::LinkageSpec:
+  case Decl::Block:
     // There is only one DeclContext for these entities.
     return 0;
 
@@ -488,6 +508,24 @@
     D->getDeclContext()->insert(Context, D);
 }
 
+/// buildLookup - Build the lookup data structure with all of the
+/// declarations in DCtx (and any other contexts linked to it or
+/// transparent contexts nested within it).
+void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) {
+  for (; DCtx; DCtx = DCtx->getNextContext()) {
+    for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D) {
+      // Insert this declaration into the lookup structure
+      insertImpl(*D);
+
+      // If this declaration is itself a transparent declaration context,
+      // add its members (recursively).
+      if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D))
+        if (InnerCtx->isTransparentContext())
+          buildLookup(Context, InnerCtx->getPrimaryContext(Context));
+    }
+  }
+}
+
 DeclContext::lookup_result 
 DeclContext::lookup(ASTContext &Context, DeclarationName Name) {
   DeclContext *PrimaryContext = getPrimaryContext(Context);
@@ -497,11 +535,8 @@
   /// If there is no lookup data structure, build one now by walking
   /// all of the linked DeclContexts (in declaration order!) and
   /// inserting their values.
-  if (LookupPtr.getPointer() == 0) {
-    for (DeclContext *DCtx = this; DCtx; DCtx = DCtx->getNextContext())
-      for (decl_iterator D = DCtx->decls_begin(); D != DCtx->decls_end(); ++D)
-        insertImpl(*D);
-  }
+  if (LookupPtr.getPointer() == 0)
+    buildLookup(Context, this);
 
   if (isLookupMap()) {
     StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(LookupPtr.getPointer());
@@ -543,9 +578,19 @@
   // someone asks for it.
   if (LookupPtr.getPointer())
     insertImpl(D);
+
+
+  // If we are a transparent context, insert into our parent context,
+  // too. This operation is recursive.
+  if (isTransparentContext())
+    getParent()->insert(Context, D);
 }
 
 void DeclContext::insertImpl(ScopedDecl *D) {
+  // Skip unnamed declarations.
+  if (!D->getDeclName())
+    return;
+
   bool MayBeRedeclaration = true;
 
   if (!isLookupMap()) {
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 27065a7..66afac8 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -291,42 +291,10 @@
   return new (Mem) OverloadedFunctionDecl(DC, N);
 }
 
-LinkageSpecDecl::LinkageSpecDecl(SourceLocation L, LanguageIDs lang, 
-                                 Decl **InDecls, unsigned InNumDecls)
-  : Decl(LinkageSpec, L), Language(lang), HadBraces(true),
-    Decls(0), NumDecls(InNumDecls) {
-  Decl **NewDecls = new Decl*[NumDecls];
-  for (unsigned I = 0; I < NumDecls; ++I)
-    NewDecls[I] = InDecls[I];
-  Decls = NewDecls;
-}
-
-LinkageSpecDecl::~LinkageSpecDecl() {
-  if (HadBraces)
-    delete [] (Decl**)Decls;
-}
-
 LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
+                                         DeclContext *DC, 
                                          SourceLocation L,
-                                         LanguageIDs Lang, Decl *D) {
+                                         LanguageIDs Lang, bool Braces) {
   void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
-  return new (Mem) LinkageSpecDecl(L, Lang, D);
-}
-
-LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,
-                                         SourceLocation L,
-                                         LanguageIDs Lang, 
-                                         Decl **Decls, unsigned NumDecls) {
-  void *Mem = C.getAllocator().Allocate<LinkageSpecDecl>();
-  return new (Mem) LinkageSpecDecl(L, Lang, Decls, NumDecls);
-}
-
-LinkageSpecDecl::decl_const_iterator LinkageSpecDecl::decls_begin() const {
-  if (hasBraces()) return (Decl**)Decls;
-  else return (Decl**)&Decls;
-}
-
-LinkageSpecDecl::decl_iterator LinkageSpecDecl::decls_end() const {
-  if (hasBraces()) return (Decl**)Decls + NumDecls;
-  else return (Decl**)&Decls + 1;
+  return new (Mem) LinkageSpecDecl(DC, L, Lang, Braces);
 }
diff --git a/lib/AST/DeclSerialization.cpp b/lib/AST/DeclSerialization.cpp
index 68412f9..0a29813 100644
--- a/lib/AST/DeclSerialization.cpp
+++ b/lib/AST/DeclSerialization.cpp
@@ -686,29 +686,12 @@
   Decl::EmitInRec(S);
   S.EmitInt(getLanguage());
   S.EmitBool(HadBraces);
-  if (HadBraces) {
-    S.EmitInt(NumDecls);
-    for (decl_const_iterator D = decls_begin(), DEnd = decls_end(); 
-         D != DEnd; ++D)
-      S.EmitPtr(*D);
-  } else {
-    S.EmitPtr((Decl*)Decls);
-  }
 }
 
 void LinkageSpecDecl::ReadInRec(Deserializer& D, ASTContext& C) {
   Decl::ReadInRec(D, C);
   Language = static_cast<LanguageIDs>(D.ReadInt());
   HadBraces = D.ReadBool();
-  if (HadBraces) {
-    NumDecls = D.ReadInt();
-    Decl **NewDecls = new Decl*[NumDecls];
-    Decls = NewDecls;
-    for (unsigned I = 0; I < NumDecls; ++I)
-      D.ReadPtr(NewDecls[I]);
-  } else {
-    D.ReadPtr(this->Decls);
-  }
 }
 
 //===----------------------------------------------------------------------===//