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/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index a63db14..94f2fdc 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -260,24 +260,40 @@
 }
 
 NamedDecl *
-ASTContext::getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD) {
+ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) {
   llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos
-    = InstantiatedFromUnresolvedUsingDecl.find(UUD);
-  if (Pos == InstantiatedFromUnresolvedUsingDecl.end())
+    = InstantiatedFromUsingDecl.find(UUD);
+  if (Pos == InstantiatedFromUsingDecl.end())
     return 0;
 
   return Pos->second;
 }
 
 void
-ASTContext::setInstantiatedFromUnresolvedUsingDecl(UsingDecl *UD,
-                                                   NamedDecl *UUD) {
-  assert((isa<UnresolvedUsingValueDecl>(UUD) ||
-          isa<UnresolvedUsingTypenameDecl>(UUD)) && 
-         "original declaration is not an unresolved using decl");
-  assert(!InstantiatedFromUnresolvedUsingDecl[UD] &&
-         "Already noted what using decl what instantiated from");
-  InstantiatedFromUnresolvedUsingDecl[UD] = UUD;
+ASTContext::setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern) {
+  assert((isa<UsingDecl>(Pattern) ||
+          isa<UnresolvedUsingValueDecl>(Pattern) ||
+          isa<UnresolvedUsingTypenameDecl>(Pattern)) && 
+         "pattern decl is not a using decl");
+  assert(!InstantiatedFromUsingDecl[Inst] && "pattern already exists");
+  InstantiatedFromUsingDecl[Inst] = Pattern;
+}
+
+UsingShadowDecl *
+ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) {
+  llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos
+    = InstantiatedFromUsingShadowDecl.find(Inst);
+  if (Pos == InstantiatedFromUsingShadowDecl.end())
+    return 0;
+
+  return Pos->second;
+}
+
+void
+ASTContext::setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst,
+                                               UsingShadowDecl *Pattern) {
+  assert(!InstantiatedFromUsingShadowDecl[Inst] && "pattern already exists");
+  InstantiatedFromUsingShadowDecl[Inst] = Pattern;
 }
 
 FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) {
@@ -1766,6 +1782,9 @@
       Decl->TypeForDecl = PrevDecl->TypeForDecl;
     else
       Decl->TypeForDecl = new (*this, TypeAlignment) EnumType(Enum);
+  } else if (UnresolvedUsingTypenameDecl *Using =
+               dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) {
+    Decl->TypeForDecl = new (*this, TypeAlignment) UnresolvedUsingType(Using);
   } else
     assert(false && "TypeDecl without a type?");
 
diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp
index 50a5120..3ccb7a9 100644
--- a/lib/AST/TypeLoc.cpp
+++ b/lib/AST/TypeLoc.cpp
@@ -94,3 +94,32 @@
     TypeLocInitializer(Loc).Visit(TL);
   } while ((TL = TL.getNextTypeLoc()));
 }
+
+namespace {
+  struct TSTChecker : public TypeLocVisitor<TSTChecker, bool> {
+    // Overload resolution does the real work for us.
+    static bool isTypeSpec(TypeSpecTypeLoc _) { return true; }
+    static bool isTypeSpec(TypeLoc _) { return false; }
+
+#define ABSTRACT_TYPELOC(CLASS, PARENT)
+#define TYPELOC(CLASS, PARENT) \
+    bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
+      return isTypeSpec(TyLoc); \
+    }
+#include "clang/AST/TypeLocNodes.def"
+  };
+}
+
+
+/// \brief Determines if the given type loc corresponds to a
+/// TypeSpecTypeLoc.  Since there is not actually a TypeSpecType in
+/// the type hierarchy, this is made somewhat complicated.
+///
+/// There are a lot of types that currently use TypeSpecTypeLoc
+/// because it's a convenient base class.  Ideally we would not accept
+/// those here, but ideally we would have better implementations for
+/// them.
+bool TypeSpecTypeLoc::classof(const TypeLoc *TL) {
+  if (TL->getType().hasLocalQualifiers()) return false;
+  return TSTChecker().Visit(*TL);
+}
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 3d7a537..2f58ebe 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -303,6 +303,15 @@
   Print(T->getResultType(), S);
 }
 
+void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T,
+                                       std::string &S) {
+  IdentifierInfo *II = T->getDecl()->getIdentifier();
+  if (S.empty())
+    S = II->getName().str();
+  else
+    S = II->getName().str() + ' ' + S;
+}
+
 void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { 
   if (!S.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     S = ' ' + S;
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 4d021e8..df708ed 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -843,6 +843,12 @@
 
 // <type>            ::= <class-enum-type>
 // <class-enum-type> ::= <name>
+void CXXNameMangler::mangleType(const UnresolvedUsingType *T) {
+  mangleName(T->getDecl());
+}
+
+// <type>            ::= <class-enum-type>
+// <class-enum-type> ::= <name>
 void CXXNameMangler::mangleType(const EnumType *T) {
   mangleType(static_cast<const TagType*>(T));
 }
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 40eb9ca..811f9ed 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -1880,6 +1880,10 @@
                                     Exceptions.data());
   }
 
+  case pch::TYPE_UNRESOLVED_USING:
+    return Context->getTypeDeclType(
+             cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0])));
+
   case pch::TYPE_TYPEDEF:
     assert(Record.size() == 1 && "incorrect encoding of typedef type");
     return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
@@ -2044,6 +2048,9 @@
 void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
   VisitFunctionTypeLoc(TL);
 }
+void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
+}
 void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
   TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index e79f9c9..0e6d1d2 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -166,6 +166,14 @@
   Code = pch::TYPE_FUNCTION_PROTO;
 }
 
+#if 0
+// For when we want it....
+void PCHTypeWriter::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
+  Writer.AddDeclRef(T->getDecl(), Record);
+  Code = pch::TYPE_UNRESOLVED_USING;
+}
+#endif
+
 void PCHTypeWriter::VisitTypedefType(const TypedefType *T) {
   Writer.AddDeclRef(T->getDecl(), Record);
   Code = pch::TYPE_TYPEDEF;
@@ -337,6 +345,9 @@
 void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
   VisitFunctionTypeLoc(TL);
 }
+void TypeLocWriter::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+  Writer.AddSourceLocation(TL.getNameLoc(), Record);
+}
 void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
   Writer.AddSourceLocation(TL.getNameLoc(), Record);
 }
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>());
 }