Incremental progress on using declarations.  Split UnresolvedUsingDecl into
two classes, one for typenames and one for values;  this seems to have some
support from Doug if not necessarily from the extremely-vague-on-this-point
standard.  Track the location of the 'typename' keyword in a using-typename
decl.  Make a new lookup result for unresolved values and deal with it in
most places.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89184 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index b3db88a..35a7d78 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1110,6 +1110,11 @@
       /// functions into an OverloadedFunctionDecl.
       FoundOverloaded,
 
+      /// @brief Name lookup found an unresolvable value declaration
+      /// and cannot yet complete.  This only happens in C++ dependent
+      /// contexts with dependent using declarations.
+      FoundUnresolvedValue,
+
       /// @brief Name lookup results in an ambiguity; use
       /// getAmbiguityKind to figure out what kind of ambiguity
       /// we have.
@@ -1417,6 +1422,7 @@
       assert(ResultKind != NotFound || Decls.size() == 0);
       assert(ResultKind != Found || Decls.size() == 1);
       assert(ResultKind == NotFound || ResultKind == Found ||
+             ResultKind == FoundUnresolvedValue ||
              (ResultKind == Ambiguous && Ambiguity == AmbiguousBaseSubobjects)
              || Decls.size() > 1);
       assert((Paths != NULL) == (ResultKind == Ambiguous &&
@@ -2017,7 +2023,9 @@
                                    SourceLocation IdentLoc,
                                    DeclarationName Name,
                                    AttributeList *AttrList,
-                                   bool IsTypeName);
+                                   bool IsInstantiation,
+                                   bool IsTypeName,
+                                   SourceLocation TypenameLoc);
 
   virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope,
                                           AccessSpecifier AS,
@@ -2025,7 +2033,8 @@
                                           const CXXScopeSpec &SS,
                                           UnqualifiedId &Name,
                                           AttributeList *AttrList,
-                                          bool IsTypeName);
+                                          bool IsTypeName,
+                                          SourceLocation TypenameLoc);
 
   /// AddCXXDirectInitializerToDecl - This action is called immediately after
   /// ActOnDeclarator, when a C++ direct initializer is present.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 2228b41..3f20498 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -94,6 +94,7 @@
   switch (Result.getResultKind()) {
   case LookupResult::NotFound:
   case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
     return 0;
 
   case LookupResult::Ambiguous:
@@ -166,6 +167,10 @@
     
   } else if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(IIDecl)) {
     T = Context.getObjCInterfaceType(IDecl);
+  } else if (UnresolvedUsingTypenameDecl *UUDecl =
+               dyn_cast<UnresolvedUsingTypenameDecl>(IIDecl)) {
+    // FIXME: preserve source structure information.
+    T = Context.getTypenameType(UUDecl->getTargetNestedNameSpecifier(), &II);
   } else {
     // If it's not plausibly a type, suppress diagnostics.
     Result.suppressDiagnostics();
@@ -2446,7 +2451,9 @@
 }
 
 static bool isUsingDecl(Decl *D) {
-  return isa<UsingDecl>(D) || isa<UnresolvedUsingDecl>(D);
+  return isa<UsingDecl>(D) ||
+         isa<UnresolvedUsingTypenameDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
 }
 
 /// \brief Data used with FindOverriddenMethod
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4f04bd2..cb18064 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2809,7 +2809,8 @@
                                             const CXXScopeSpec &SS,
                                             UnqualifiedId &Name,
                                             AttributeList *AttrList,
-                                            bool IsTypeName) {
+                                            bool IsTypeName,
+                                            SourceLocation TypenameLoc) {
   assert(S->getFlags() & Scope::DeclScope && "Invalid Scope.");
 
   switch (Name.getKind()) {
@@ -2837,7 +2838,9 @@
   DeclarationName TargetName = GetNameFromUnqualifiedId(Name);
   NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS,
                                         Name.getSourceRange().getBegin(),
-                                        TargetName, AttrList, IsTypeName);
+                                        TargetName, AttrList,
+                                        /* IsInstantiation */ false,
+                                        IsTypeName, TypenameLoc);
   if (UD) {
     PushOnScopeChains(UD, S);
     UD->setAccess(AS);
@@ -2872,13 +2875,20 @@
   return Shadow;
 }
 
+/// Builds a using declaration.
+///
+/// \param IsInstantiation - Whether this call arises from an
+///   instantiation of an unresolved using declaration.  We treat
+///   the lookup differently for these declarations.
 NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                        SourceLocation UsingLoc,
                                        const CXXScopeSpec &SS,
                                        SourceLocation IdentLoc,
                                        DeclarationName Name,
                                        AttributeList *AttrList,
-                                       bool IsTypeName) {
+                                       bool IsInstantiation,
+                                       bool IsTypeName,
+                                       SourceLocation TypenameLoc) {
   assert(!SS.isInvalid() && "Invalid CXXScopeSpec.");
   assert(IdentLoc.isValid() && "Invalid TargetName location.");
 
@@ -2895,9 +2905,16 @@
 
   DeclContext *LookupContext = computeDeclContext(SS);
   if (!LookupContext) {
-    return UnresolvedUsingDecl::Create(Context, CurContext, UsingLoc,
-                                       SS.getRange(), NNS,
-                                       IdentLoc, Name, IsTypeName);
+    if (IsTypeName) {
+      return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+                                                 UsingLoc, TypenameLoc,
+                                                 SS.getRange(), NNS,
+                                                 IdentLoc, Name);
+    } else {
+      return UnresolvedUsingValueDecl::Create(Context, CurContext,
+                                              UsingLoc, SS.getRange(), NNS,
+                                              IdentLoc, Name);
+    }
   }
 
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
@@ -2929,7 +2946,12 @@
   // 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);
+
+  // We don't hide tags behind ordinary decls if we're in a
+  // non-dependent context, but in a dependent context, this is
+  // important for the stability of two-phase lookup.
+  if (!IsInstantiation)
+    R.setHideTags(false);
 
   LookupQualifiedName(R, LookupContext);
 
@@ -2942,11 +2964,27 @@
   if (R.isAmbiguous())
     return 0;
 
-  if (IsTypeName &&
-      (R.getResultKind() != LookupResult::Found
-       || !isa<TypeDecl>(R.getFoundDecl()))) {
-    Diag(IdentLoc, diag::err_using_typename_non_type);
-    return 0;
+  if (IsTypeName) {
+    // If we asked for a typename and got a non-type decl, error out.
+    if (R.getResultKind() != LookupResult::Found
+        || !isa<TypeDecl>(R.getFoundDecl())) {
+      Diag(IdentLoc, diag::err_using_typename_non_type);
+      for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
+        Diag((*I)->getUnderlyingDecl()->getLocation(),
+             diag::note_using_decl_target);
+      return 0;
+    }
+  } else {
+    // If we asked for a non-typename and we got a type, error out,
+    // but only if this is an instantiation of an unresolved using
+    // decl.  Otherwise just silently find the type name.
+    if (IsInstantiation &&
+        R.getResultKind() == LookupResult::Found &&
+        isa<TypeDecl>(R.getFoundDecl())) {
+      Diag(IdentLoc, diag::err_using_dependent_value_is_type);
+      Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
+      return 0;
+    }
   }
 
   // C++0x N2914 [namespace.udecl]p6:
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 2e33200..43f150f 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -977,7 +977,7 @@
   else if (TemplateDecl *Template = dyn_cast<TemplateDecl>(D))
     return BuildDeclRefExpr(Template, Context.OverloadTy, Loc,
                             false, false, SS);
-  else if (UnresolvedUsingDecl *UD = dyn_cast<UnresolvedUsingDecl>(D))
+  else if (UnresolvedUsingValueDecl *UD = dyn_cast<UnresolvedUsingValueDecl>(D))
     return BuildDeclRefExpr(UD, Context.DependentTy, Loc,
                             /*TypeDependent=*/true,
                             /*ValueDependent=*/true, SS);
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index d736d42..f37fb8b 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -245,7 +245,12 @@
   unsigned N = Decls.size();
 
   // Fast case: no possible ambiguity.
-  if (N <= 1) return;
+  if (N == 0) return;
+  if (N == 1) {
+    if (isa<UnresolvedUsingValueDecl>(Decls[0]))
+      ResultKind = FoundUnresolvedValue;
+    return;
+  }
 
   // Don't do any extra resolution if we've already resolved as ambiguous.
   if (ResultKind == Ambiguous) return;
@@ -254,6 +259,7 @@
 
   bool Ambiguous = false;
   bool HasTag = false, HasFunction = false, HasNonFunction = false;
+  bool HasUnresolved = false;
 
   unsigned UniqueTagIndex = 0;
   
@@ -266,12 +272,15 @@
       // If it's not unique, pull something off the back (and
       // continue at this index).
       Decls[I] = Decls[--N];
-    } else if (isa<UnresolvedUsingDecl>(D)) {
-      // FIXME: support unresolved using decls
+    } else if (isa<UnresolvedUsingValueDecl>(D)) {
+      // FIXME: support unresolved using value declarations
       Decls[I] = Decls[--N];
     } else {
       // Otherwise, do some decl type analysis and then continue.
-      if (isa<TagDecl>(D)) {
+
+      if (isa<UnresolvedUsingValueDecl>(D)) {
+        HasUnresolved = true;
+      } else if (isa<TagDecl>(D)) {
         if (HasTag)
           Ambiguous = true;
         UniqueTagIndex = I;
@@ -296,7 +305,8 @@
   //   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 (HideTags && HasTag && !Ambiguous && (HasFunction || HasNonFunction))
+  if (HideTags && HasTag && !Ambiguous && !HasUnresolved &&
+      (HasFunction || HasNonFunction))
     Decls[UniqueTagIndex] = Decls[--N];
 
   Decls.set_size(N);
@@ -306,6 +316,8 @@
 
   if (Ambiguous)
     setAmbiguous(LookupResult::AmbiguousReference);
+  else if (HasUnresolved)
+    ResultKind = LookupResult::FoundUnresolvedValue;
   else if (N > 1)
     ResultKind = LookupResult::FoundOverloaded;
   else
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index a799ddb..28fa6bd 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -4501,6 +4501,10 @@
     Referenced = Result.getFoundDecl();
     break;
 
+  case LookupResult::FoundUnresolvedValue:
+    llvm::llvm_unreachable("unresolved using decl in non-dependent context");
+    return QualType();
+
   case LookupResult::FoundOverloaded:
     DiagID = diag::err_typename_nested_not_type;
     Referenced = *Result.begin();
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 00ef407..8d5741d 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -66,7 +66,8 @@
     Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
-    Decl *VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D);
+    Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
+    Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
 
     // Base case. FIXME: Remove once we can instantiate everything.
     Decl *VisitDecl(Decl *D) {
@@ -1025,8 +1026,8 @@
   return Inst;
 }
 
-Decl *
-TemplateDeclInstantiator::VisitUnresolvedUsingDecl(UnresolvedUsingDecl *D) {
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
   NestedNameSpecifier *NNS =
     SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
                                      D->getTargetNestedNameRange(),
@@ -1040,8 +1041,35 @@
 
   NamedDecl *UD =
     SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
-                                  D->getLocation(), SS, D->getTargetNameLocation(),
-                                  D->getDeclName(), 0, D->isTypeName());
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ true, D->getTypenameLoc());
+  if (UD)
+    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
+                                                           D);
+  return UD;
+}
+
+Decl * TemplateDeclInstantiator
+    ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) {
+  NestedNameSpecifier *NNS =
+    SemaRef.SubstNestedNameSpecifier(D->getTargetNestedNameSpecifier(),
+                                     D->getTargetNestedNameRange(),
+                                     TemplateArgs);
+  if (!NNS)
+    return 0;
+
+  CXXScopeSpec SS;
+  SS.setRange(D->getTargetNestedNameRange());
+  SS.setScopeRep(NNS);
+
+  NamedDecl *UD =
+    SemaRef.BuildUsingDeclaration(/*Scope*/ 0, D->getAccess(),
+                                  D->getUsingLoc(), SS, D->getLocation(),
+                                  D->getDeclName(), 0,
+                                  /*instantiation*/ true,
+                                  /*typename*/ false, SourceLocation());
   if (UD)
     SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
                                                            D);
@@ -1724,7 +1752,13 @@
   return false;
 }
 
-static bool isInstantiationOf(UnresolvedUsingDecl *Pattern,
+static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
   return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
@@ -1747,7 +1781,15 @@
 
 static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
   if (D->getKind() != Other->getKind()) {
-    if (UnresolvedUsingDecl *UUD = dyn_cast<UnresolvedUsingDecl>(D)) {
+    if (UnresolvedUsingTypenameDecl *UUD
+          = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
+        return isInstantiationOf(UUD, UD, Ctx);
+      }
+    }
+
+    if (UnresolvedUsingValueDecl *UUD
+          = dyn_cast<UnresolvedUsingValueDecl>(D)) {
       if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) {
         return isInstantiationOf(UUD, UD, Ctx);
       }