Instead of hanging a using declaration's target decls directly off the using    
decl, create shadow declarations and put them in scope like normal.
Work in progress.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89048 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index a6996a4..bdc8047 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -289,6 +289,10 @@
   if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD))
     return true;
 
+  if (isa<UsingShadowDecl>(this) && isa<UsingShadowDecl>(OldD))
+    return cast<UsingShadowDecl>(this)->getTargetDecl() ==
+           cast<UsingShadowDecl>(OldD)->getTargetDecl();
+
   // For non-function declarations, if the declarations are of the
   // same kind then this must be a redeclaration, or semantic analysis
   // would not have given us the new declaration.
@@ -308,7 +312,7 @@
 NamedDecl *NamedDecl::getUnderlyingDecl() {
   NamedDecl *ND = this;
   while (true) {
-    if (UsingDecl *UD = dyn_cast<UsingDecl>(ND))
+    if (UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(ND))
       ND = UD->getTargetDecl();
     else if (ObjCCompatibleAliasDecl *AD
               = dyn_cast<ObjCCompatibleAliasDecl>(ND))
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 6cfdcdd..da3b19d 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -97,7 +97,7 @@
 }
 
 bool Decl::isFunctionOrFunctionTemplate() const {
-  if (const UsingDecl *UD = dyn_cast<UsingDecl>(this))
+  if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
     return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
 
   return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
@@ -189,10 +189,11 @@
 
 unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
   switch (DeclKind) {
-    default:
-      if (DeclKind >= FunctionFirst && DeclKind <= FunctionLast)
-        return IDNS_Ordinary;
-      assert(0 && "Unknown decl kind!");
+    case Function:
+    case CXXMethod:
+    case CXXConstructor:
+    case CXXDestructor:
+    case CXXConversion:
     case OverloadedFunction:
     case Typedef:
     case EnumConstant:
@@ -200,8 +201,6 @@
     case ImplicitParam:
     case ParmVar:
     case NonTypeTemplateParm:
-    case Using:
-    case UnresolvedUsing:
     case ObjCMethod:
     case ObjCContainer:
     case ObjCCategory:
@@ -210,6 +209,15 @@
     case ObjCCompatibleAlias:
       return IDNS_Ordinary;
 
+    case UsingShadow:
+      return 0; // we'll actually overwrite this later
+
+    case UnresolvedUsing:
+      return IDNS_Tag | IDNS_Ordinary | IDNS_Using;
+
+    case Using:
+      return IDNS_Using;
+
     case ObjCProtocol:
       return IDNS_ObjCProtocol;
 
@@ -256,6 +264,8 @@
     case ClassTemplatePartialSpecialization:
       return 0;
   }
+
+  return 0;
 }
 
 void Decl::addAttr(Attr *NewAttr) {
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 3768796..520206d 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -914,11 +914,10 @@
 }
 
 UsingDecl *UsingDecl::Create(ASTContext &C, DeclContext *DC,
-      SourceLocation L, SourceRange NNR, SourceLocation TargetNL,
-      SourceLocation UL, NamedDecl* Target,
-      NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) {
-  return new (C) UsingDecl(DC, L, NNR, TargetNL, UL, Target,
-      TargetNNS, IsTypeNameArg);
+      SourceLocation L, SourceRange NNR, SourceLocation UL,
+      NestedNameSpecifier* TargetNNS, DeclarationName Name,
+      bool IsTypeNameArg) {
+  return new (C) UsingDecl(DC, L, NNR, UL, TargetNNS, Name, IsTypeNameArg);
 }
 
 UnresolvedUsingDecl *UnresolvedUsingDecl::Create(ASTContext &C, DeclContext *DC,
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index b88a971..199ed35 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -73,6 +73,7 @@
     void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
     void VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
     void VisitUsingDecl(UsingDecl *D);
+    void VisitUsingShadowDecl(UsingShadowDecl *D);
   };
 }
 
@@ -825,7 +826,7 @@
 void DeclPrinter::VisitUsingDecl(UsingDecl *D) {
   Out << "using ";
   D->getTargetNestedNameDecl()->print(Out, Policy);
-  Out << D->getTargetDecl()->getNameAsString();
+  Out << D->getNameAsString();
 }
 
 void DeclPrinter::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
@@ -833,3 +834,7 @@
   D->getTargetNestedNameSpecifier()->print(Out, Policy);
   Out << D->getTargetName().getAsString();
 }
+
+void DeclPrinter::VisitUsingShadowDecl(UsingShadowDecl *D) {
+  // ignore
+}
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index acf52c9..fea6f80 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1197,6 +1197,7 @@
         LookupKind(LookupKind),
         IDNS(0),
         Redecl(Redecl != NotForRedeclaration),
+        HideTags(true),
         Diagnose(Redecl == NotForRedeclaration)
     {}
 
@@ -1212,6 +1213,7 @@
         LookupKind(Other.LookupKind),
         IDNS(Other.IDNS),
         Redecl(Other.Redecl),
+        HideTags(Other.HideTags),
         Diagnose(false)
     {}
 
@@ -1235,6 +1237,12 @@
       return Redecl;
     }
 
+    /// Sets whether tag declarations should be hidden by non-tag
+    /// declarations during resolution.  The default is true.
+    void setHideTags(bool Hide) {
+      HideTags = Hide;
+    }
+
     /// The identifier namespace of this lookup.  This information is
     /// private to the lookup routines.
     unsigned getIdentifierNamespace() const {
@@ -1441,6 +1449,10 @@
     unsigned IDNS; // ill-defined until set by lookup
     bool Redecl;
 
+    /// \brief True if tag declarations should be hidden if non-tags
+    ///   are present
+    bool HideTags;
+
     bool Diagnose;
   };
 
@@ -2007,7 +2019,8 @@
                                            SourceLocation IdentLoc,
                                            IdentifierInfo *Ident);
 
-  NamedDecl *BuildUsingDeclaration(SourceLocation UsingLoc,
+  NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                   SourceLocation UsingLoc,
                                    const CXXScopeSpec &SS,
                                    SourceLocation IdentLoc,
                                    DeclarationName Name,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 84262a4..de30441 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -198,7 +198,7 @@
     return;
       
   // Look through using declarations.
-  if (UsingDecl *Using = dyn_cast<UsingDecl>(R.Declaration))
+  if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration))
     MaybeAddResult(Result(Using->getTargetDecl(), R.Rank, R.Qualifier),
                    CurContext);
   
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 9ba03a9..698d81e 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2835,7 +2835,7 @@
   }
   
   DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
-  NamedDecl *UD = BuildUsingDeclaration(UsingLoc, SS, 
+  NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
                                         Name.getSourceRange().getBegin(),
                                         TargetName, AttrList, IsTypeName);
   if (UD) {
@@ -2846,7 +2846,34 @@
   return DeclPtrTy::make(UD);
 }
 
-NamedDecl *Sema::BuildUsingDeclaration(SourceLocation UsingLoc,
+/// Builds a shadow declaration corresponding to a 'using' declaration.
+static UsingShadowDecl *BuildUsingShadowDecl(Sema &SemaRef, Scope *S,
+                                             AccessSpecifier AS,
+                                             UsingDecl *UD, NamedDecl *Orig) {
+  // FIXME: diagnose hiding, collisions
+
+  // If we resolved to another shadow declaration, just coalesce them.
+  if (isa<UsingShadowDecl>(Orig)) {
+    Orig = cast<UsingShadowDecl>(Orig)->getTargetDecl();
+    assert(!isa<UsingShadowDecl>(Orig) && "nested shadow declaration");
+  }
+  
+  UsingShadowDecl *Shadow
+    = UsingShadowDecl::Create(SemaRef.Context, SemaRef.CurContext,
+                              UD->getLocation(), UD, Orig);
+  UD->addShadowDecl(Shadow);
+
+  if (S)
+    SemaRef.PushOnScopeChains(Shadow, S);
+  else
+    SemaRef.CurContext->addDecl(Shadow);
+  Shadow->setAccess(AS);
+
+  return Shadow;
+}
+
+NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
+                                       SourceLocation UsingLoc,
                                        const CXXScopeSpec &SS,
                                        SourceLocation IdentLoc,
                                        DeclarationName Name,
@@ -2880,7 +2907,7 @@
     // anonymous union that is a member of a base class of the class being
     // defined, or shall refer to an enumerator for an enumeration type that is
     // a member of a base class of the class being defined.
-
+    
     CXXRecordDecl *LookupRD = dyn_cast<CXXRecordDecl>(LookupContext);
     if (!LookupRD || !RD->isDerivedFrom(LookupRD)) {
       Diag(SS.getRange().getBegin(),
@@ -2898,8 +2925,12 @@
     }
   }
 
-  // Lookup target name.
+  // Look up the target name.  Unlike most lookups, we do not want to
+  // hide tag declarations: tag names are visible through the using
+  // declaration even if hidden by ordinary names.
   LookupResult R(*this, Name, IdentLoc, LookupOrdinaryName);
+  R.setHideTags(false);
+
   LookupQualifiedName(R, LookupContext);
 
   if (R.empty()) {
@@ -2908,24 +2939,33 @@
     return 0;
   }
 
-  // FIXME: handle ambiguity?
-  NamedDecl *ND = R.getAsSingleDecl(Context);
+  if (R.isAmbiguous())
+    return 0;
 
-  if (IsTypeName && !isa<TypeDecl>(ND)) {
+  if (IsTypeName &&
+      (R.getResultKind() != LookupResult::Found
+       || !isa<TypeDecl>(R.getFoundDecl()))) {
     Diag(IdentLoc, diag::err_using_typename_non_type);
     return 0;
   }
 
   // C++0x N2914 [namespace.udecl]p6:
   // A using-declaration shall not name a namespace.
-  if (isa<NamespaceDecl>(ND)) {
+  if (R.getResultKind() == LookupResult::Found
+      && isa<NamespaceDecl>(R.getFoundDecl())) {
     Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
       << SS.getRange();
     return 0;
   }
 
-  return UsingDecl::Create(Context, CurContext, IdentLoc, SS.getRange(),
-                           ND->getLocation(), UsingLoc, ND, NNS, IsTypeName);
+  UsingDecl *UD = UsingDecl::Create(Context, CurContext, IdentLoc,
+                                    SS.getRange(), UsingLoc, NNS, Name,
+                                    IsTypeName);
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+    BuildUsingShadowDecl(*this, S, AS, UD, *I);
+
+  return UD;
 }
 
 /// getNamespaceDecl - Returns the namespace a decl represents. If the decl
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 1c7dce0..58b95fc6 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -297,7 +297,7 @@
   //   wherever the object, function, or enumerator name is visible.
   // But it's still an error if there are distinct tag types found,
   // even if they're not visible. (ref?)
-  if (HasTag && !Ambiguous && (HasFunction || HasNonFunction))
+  if (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction))
     Decls[UniqueTagIndex] = Decls[--N];
 
   Decls.set_size(N);
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 721bfb9..58fe59e 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -788,10 +788,46 @@
   if (!InstD)
     return SemaRef.ExprError();
 
-  // If we instantiated an UnresolvedUsingDecl and got back an UsingDecl,
-  // we need to get the underlying decl.
-  // FIXME: Is this correct? Maybe FindInstantiatedDecl should do this?
-  InstD = InstD->getUnderlyingDecl();
+  // Flatten using declarations into their shadow declarations.
+  if (isa<UsingDecl>(InstD)) {
+    UsingDecl *UD = cast<UsingDecl>(InstD);
+
+    bool HasNonFunction = false;
+
+    llvm::SmallVector<NamedDecl*, 8> Decls;
+    for (UsingDecl::shadow_iterator I = UD->shadow_begin(),
+                                    E = UD->shadow_end(); I != E; ++I) {
+      NamedDecl *TD = (*I)->getTargetDecl();
+      if (!TD->isFunctionOrFunctionTemplate())
+        HasNonFunction = true;
+
+      Decls.push_back(TD);
+    }
+
+    if (Decls.empty())
+      return SemaRef.ExprError();
+
+    if (Decls.size() == 1)
+      InstD = Decls[0];
+    else if (!HasNonFunction) {
+      OverloadedFunctionDecl *OFD
+        = OverloadedFunctionDecl::Create(SemaRef.Context,
+                                         UD->getDeclContext(),
+                                         UD->getDeclName());
+      for (llvm::SmallVectorImpl<NamedDecl*>::iterator I = Decls.begin(),
+                                                E = Decls.end(); I != E; ++I)
+        if (isa<FunctionDecl>(*I))
+          OFD->addOverload(cast<FunctionDecl>(*I));
+        else
+          OFD->addOverload(cast<FunctionTemplateDecl>(*I));
+
+      InstD = OFD;
+    } else {
+      // FIXME
+      assert(false && "using declaration resolved to mixed set");
+      return SemaRef.ExprError();
+    }
+  }
 
   CXXScopeSpec SS;
   NestedNameSpecifier *Qualifier = 0;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index a37f3a2..208352f 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1019,9 +1019,9 @@
   SS.setScopeRep(NNS);
 
   NamedDecl *UD =
-    SemaRef.BuildUsingDeclaration(D->getLocation(), SS,
-                                  D->getTargetNameLocation(),
-                                  D->getTargetName(), 0, D->isTypeName());
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getLocation(), SS, D->getTargetNameLocation(),
+                                  D->getDeclName(), 0, D->isTypeName());
   if (UD)
     SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
                                                            D);