Fix "using typename" and the instantiation of non-dependent using declarations.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90614 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 616151e..9606821 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -1729,6 +1729,10 @@
                                            SourceLocation IdentLoc,
                                            IdentifierInfo *Ident);
 
+  bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                               const CXXScopeSpec &SS,
+                               SourceLocation NameLoc);
+
   NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS,
                                    SourceLocation UsingLoc,
                                    const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 58b5633..992bb80 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2900,10 +2900,8 @@
                                         TargetName, AttrList,
                                         /* IsInstantiation */ false,
                                         IsTypeName, TypenameLoc);
-  if (UD) {
-    PushOnScopeChains(UD, S);
-    UD->setAccess(AS);
-  }
+  if (UD)
+    PushOnScopeChains(UD, S, /*AddToContext*/ false);
 
   return DeclPtrTy::make(UD);
 }
@@ -2962,19 +2960,33 @@
   NestedNameSpecifier *NNS =
     static_cast<NestedNameSpecifier *>(SS.getScopeRep());
 
+  if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
+    return 0;
+
   DeclContext *LookupContext = computeDeclContext(SS);
+  NamedDecl *D;
   if (!LookupContext) {
     if (IsTypeName) {
-      return UnresolvedUsingTypenameDecl::Create(Context, CurContext,
-                                                 UsingLoc, TypenameLoc,
-                                                 SS.getRange(), NNS,
-                                                 IdentLoc, Name);
-    } else {
-      return UnresolvedUsingValueDecl::Create(Context, CurContext,
-                                              UsingLoc, SS.getRange(), NNS,
+      // FIXME: not all declaration name kinds are legal here
+      D = UnresolvedUsingTypenameDecl::Create(Context, CurContext,
+                                              UsingLoc, TypenameLoc,
+                                              SS.getRange(), NNS,
                                               IdentLoc, Name);
+    } else {
+      D = UnresolvedUsingValueDecl::Create(Context, CurContext,
+                                           UsingLoc, SS.getRange(), NNS,
+                                           IdentLoc, Name);
     }
+  } else {
+    D = UsingDecl::Create(Context, CurContext, IdentLoc,
+                          SS.getRange(), UsingLoc, NNS, Name,
+                          IsTypeName);
   }
+  D->setAccess(AS);
+  CurContext->addDecl(D);
+
+  if (!LookupContext) return D;
+  UsingDecl *UD = cast<UsingDecl>(D);
 
   if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(CurContext)) {
     // C++0x N2914 [namespace.udecl]p3:
@@ -2989,7 +3001,8 @@
       Diag(SS.getRange().getBegin(),
            diag::err_using_decl_nested_name_specifier_is_not_a_base_class)
         << NNS << RD->getDeclName();
-      return 0;
+      UD->setInvalidDecl();
+      return UD;
     }
   } else {
     // C++0x N2914 [namespace.udecl]p8:
@@ -2997,7 +3010,8 @@
     if (isa<CXXRecordDecl>(LookupContext)) {
       Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_class_member)
         << SS.getRange();
-      return 0;
+      UD->setInvalidDecl();
+      return UD;
     }
   }
 
@@ -3017,54 +3031,63 @@
   if (R.empty()) {
     Diag(IdentLoc, diag::err_no_member) 
       << Name << LookupContext << SS.getRange();
-    return 0;
+    UD->setInvalidDecl();
+    return UD;
   }
 
-  if (R.isAmbiguous())
-    return 0;
+  if (R.isAmbiguous()) {
+    UD->setInvalidDecl();
+    return UD;
+  }
 
   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())) {
+    if (!R.getAsSingle<TypeDecl>()) {
       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;
+      UD->setInvalidDecl();
+      return UD;
     }
   } 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())) {
+    if (IsInstantiation && R.getAsSingle<TypeDecl>()) {
       Diag(IdentLoc, diag::err_using_dependent_value_is_type);
       Diag(R.getFoundDecl()->getLocation(), diag::note_using_decl_target);
-      return 0;
+      UD->setInvalidDecl();
+      return UD;
     }
   }
 
   // C++0x N2914 [namespace.udecl]p6:
   // A using-declaration shall not name a namespace.
-  if (R.getResultKind() == LookupResult::Found
-      && isa<NamespaceDecl>(R.getFoundDecl())) {
+  if (R.getAsSingle<NamespaceDecl>()) {
     Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
       << SS.getRange();
-    return 0;
+    UD->setInvalidDecl();
+    return UD;
   }
 
-  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;
 }
 
+/// Checks that the given nested-name qualifier used in a using decl
+/// in the current context is appropriately related to the current
+/// scope.  If an error is found, diagnoses it and returns true.
+bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc) {
+  // FIXME: implement
+
+  return false;
+}
+
 Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
                                              SourceLocation NamespaceLoc,
                                              SourceLocation AliasLoc,
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 613ffde..b4754db 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -2361,6 +2361,7 @@
   case Type::Enum:
   case Type::ObjCInterface:
   case Type::ObjCObjectPointer:
+  case Type::UnresolvedUsing:
 #define TYPE(Class, Base)
 #define ABSTRACT_TYPE(Class, Base)
 #define DEPENDENT_TYPE(Class, Base)
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 122e85e..6a4ac3c 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1064,8 +1064,6 @@
         Invalid = true;
       } else if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
         Fields.push_back(DeclPtrTy::make(Field));
-      else if (UsingDecl *UD = dyn_cast<UsingDecl>(NewMember))
-        Instantiation->addDecl(UD);
     } else {
       // FIXME: Eventually, a NULL return will mean that one of the
       // instantiations was a semantic disaster, and we'll want to set Invalid =
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index ec28f47..6b41d9a 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -66,6 +66,8 @@
     Decl *VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
     Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
     Decl *VisitUsingDirectiveDecl(UsingDirectiveDecl *D);
+    Decl *VisitUsingDecl(UsingDecl *D);
+    Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
     Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
     Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
 
@@ -1034,6 +1036,56 @@
   return Inst;
 }
 
+Decl *TemplateDeclInstantiator::VisitUsingDecl(UsingDecl *D) {
+  // The nested name specifier is non-dependent, so no transformation
+  // is required.
+
+  UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
+                                       D->getLocation(),
+                                       D->getNestedNameRange(),
+                                       D->getUsingLocation(),
+                                       D->getTargetNestedNameDecl(),
+                                       D->getDeclName(),
+                                       D->isTypeName());
+
+  CXXScopeSpec SS;
+  SS.setScopeRep(D->getTargetNestedNameDecl());
+  SS.setRange(D->getNestedNameRange());
+  if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+                                      D->getLocation()))
+    NewUD->setInvalidDecl();
+  SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
+  NewUD->setAccess(D->getAccess());
+  Owner->addDecl(NewUD);
+
+  // We'll transform the UsingShadowDecls as we reach them.
+
+  return NewUD;
+}
+
+Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
+  UsingDecl *InstUsing =
+    cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
+                                                 TemplateArgs));
+  NamedDecl *InstTarget =
+    cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
+                                                 TemplateArgs));
+
+  UsingShadowDecl *InstD = UsingShadowDecl::Create(SemaRef.Context, Owner,
+                                                   InstUsing->getLocation(),
+                                                   InstUsing, InstTarget);
+  InstUsing->addShadowDecl(InstD);
+
+  if (InstTarget->isInvalidDecl() || InstUsing->isInvalidDecl())
+    InstD->setInvalidDecl();
+
+  SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
+  InstD->setAccess(D->getAccess());
+  Owner->addDecl(InstD);
+
+  return InstD;
+}
+
 Decl * TemplateDeclInstantiator
     ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) {
   NestedNameSpecifier *NNS =
@@ -1054,8 +1106,8 @@
                                   /*instantiation*/ true,
                                   /*typename*/ true, D->getTypenameLoc());
   if (UD)
-    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
-                                                           D);
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
   return UD;
 }
 
@@ -1079,8 +1131,8 @@
                                   /*instantiation*/ true,
                                   /*typename*/ false, SourceLocation());
   if (UD)
-    SemaRef.Context.setInstantiatedFromUnresolvedUsingDecl(cast<UsingDecl>(UD),
-                                                           D);
+    SemaRef.Context.setInstantiatedFromUsingDecl(cast<UsingDecl>(UD), D);
+
   return UD;
 }
 
@@ -1753,16 +1805,28 @@
   return false;
 }
 
+static bool isInstantiationOf(UsingShadowDecl *Pattern,
+                              UsingShadowDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingShadowDecl(Instance) == Pattern;
+}
+
+static bool isInstantiationOf(UsingDecl *Pattern,
+                              UsingDecl *Instance,
+                              ASTContext &C) {
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
+}
+
 static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
-  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
 }
 
 static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern,
                               UsingDecl *Instance,
                               ASTContext &C) {
-  return C.getInstantiatedFromUnresolvedUsingDecl(Instance) == Pattern;
+  return C.getInstantiatedFromUsingDecl(Instance) == Pattern;
 }
 
 static bool isInstantiationOfStaticDataMember(VarDecl *Pattern,
@@ -1780,6 +1844,8 @@
   return false;
 }
 
+// Other is the prospective instantiation
+// D is the prospective pattern
 static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) {
   if (D->getKind() != Other->getKind()) {
     if (UnresolvedUsingTypenameDecl *UUD
@@ -1831,6 +1897,12 @@
     }
   }
 
+  if (UsingDecl *Using = dyn_cast<UsingDecl>(Other))
+    return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx);
+
+  if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(Other))
+    return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx);
+
   return D->getDeclName() && isa<NamedDecl>(Other) &&
     D->getDeclName() == cast<NamedDecl>(Other)->getDeclName();
 }
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index e1ac322..b029a37 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -461,6 +461,10 @@
   /// \brief Build a new unprototyped function type.
   QualType RebuildFunctionNoProtoType(QualType ResultType);
 
+  /// \brief Rebuild an unresolved typename type, given the decl that
+  /// the UnresolvedUsingTypenameDecl was transformed to.
+  QualType RebuildUnresolvedUsingType(Decl *D);
+
   /// \brief Build a new typedef type.
   QualType RebuildTypedefType(TypedefDecl *Typedef) {
     return SemaRef.Context.getTypeDeclType(Typedef);
@@ -2578,6 +2582,29 @@
   return Result;
 }
 
+template<typename Derived> QualType
+TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB,
+                                                 UnresolvedUsingTypeLoc TL) {
+  UnresolvedUsingType *T = TL.getTypePtr();
+  Decl *D = getDerived().TransformDecl(T->getDecl());
+  if (!D)
+    return QualType();
+
+  QualType Result = TL.getType();
+  if (getDerived().AlwaysRebuild() || D != T->getDecl()) {
+    Result = getDerived().RebuildUnresolvedUsingType(D);
+    if (Result.isNull())
+      return QualType();
+  }
+
+  // We might get an arbitrary type spec type back.  We should at
+  // least always get a type spec type, though.
+  TypeSpecTypeLoc NewTL = TLB.pushTypeSpec(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+
+  return Result;
+}
+
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
                                                       TypedefTypeLoc TL) {
@@ -5318,6 +5345,30 @@
 }
 
 template<typename Derived>
+QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) {
+  assert(D && "no decl found");
+  if (D->isInvalidDecl()) return QualType();
+
+  TypeDecl *Ty;
+  if (isa<UsingDecl>(D)) {
+    UsingDecl *Using = cast<UsingDecl>(D);
+    assert(Using->isTypeName() &&
+           "UnresolvedUsingTypenameDecl transformed to non-typename using");
+
+    // A valid resolved using typename decl points to exactly one type decl.
+    assert(++Using->shadow_begin() == Using->shadow_end());
+    Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl());
+    
+  } else {
+    assert(isa<UnresolvedUsingTypenameDecl>(D) &&
+           "UnresolvedUsingTypenameDecl transformed to non-using decl");
+    Ty = cast<UnresolvedUsingTypenameDecl>(D);
+  }
+
+  return SemaRef.Context.getTypeDeclType(Ty);
+}
+
+template<typename Derived>
 QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {
   return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());
 }