Track source information for template arguments and template specialization
types.  Preserve it through template instantiation.  Preserve it through PCH,
although TSTs themselves aren't serializable, so that's pretty much meaningless.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85500 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 66ee818..11a3938 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -73,6 +73,7 @@
   class TypedefDecl;
   class TemplateDecl;
   class TemplateArgument;
+  class TemplateArgumentLoc;
   class TemplateArgumentList;
   class TemplateParameterList;
   class TemplateTemplateParmDecl;
@@ -866,7 +867,7 @@
                           bool ForceRValue = false);
   void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
                                   bool HasExplicitTemplateArgs,
-                                  const TemplateArgument *ExplicitTemplateArgs,
+                              const TemplateArgumentLoc *ExplicitTemplateArgs,
                                   unsigned NumExplicitTemplateArgs,
                                   Expr *Object, Expr **Args, unsigned NumArgs,
                                   OverloadCandidateSet& CandidateSet,
@@ -874,7 +875,7 @@
                                   bool ForceRValue = false);
   void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
                                     bool HasExplicitTemplateArgs,
-                                  const TemplateArgument *ExplicitTemplateArgs,
+                           const TemplateArgumentLoc *ExplicitTemplateArgs,
                                     unsigned NumExplicitTemplateArgs,
                                     Expr **Args, unsigned NumArgs,
                                     OverloadCandidateSet& CandidateSet,
@@ -912,7 +913,7 @@
   void AddArgumentDependentLookupCandidates(DeclarationName Name,
                                             Expr **Args, unsigned NumArgs,
                                             bool HasExplicitTemplateArgs,
-                                  const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                             unsigned NumExplicitTemplateArgs,                                            
                                             OverloadCandidateSet& CandidateSet,
                                             bool PartialOverloading = false);
@@ -934,7 +935,7 @@
                                    DeclarationName &UnqualifiedName,
                                    bool &ArgumentDependentLookup,
                                    bool HasExplicitTemplateArgs,
-                                   const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                    unsigned NumExplicitTemplateArgs,
                                    Expr **Args, unsigned NumArgs,
                                    OverloadCandidateSet &CandidateSet,
@@ -943,7 +944,7 @@
   FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
                                         DeclarationName UnqualifiedName,
                                         bool HasExplicitTemplateArgs,
-                                const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                         unsigned NumExplicitTemplateArgs,
                                         SourceLocation LParenLoc,
                                         Expr **Args, unsigned NumArgs,
@@ -1708,7 +1709,7 @@
                                             DeclarationName MemberName,
                                             bool HasExplicitTemplateArgs,
                                             SourceLocation LAngleLoc,
-                                const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                             unsigned NumExplicitTemplateArgs,
                                             SourceLocation RAngleLoc,
                                             DeclPtrTy ImplDecl,
@@ -1741,7 +1742,7 @@
                                SourceRange &QualifierRange,
                                bool &ArgumentDependentLookup,
                                bool &HasExplicitTemplateArguments,
-                               const TemplateArgument *&ExplicitTemplateArgs,
+                            const TemplateArgumentLoc *&ExplicitTemplateArgs,
                                unsigned &NumExplicitTemplateArgs);
     
   /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments.
@@ -2505,13 +2506,13 @@
                                 AccessSpecifier AS);
 
   void translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
-                                  SourceLocation *TemplateArgLocs,
-                        llvm::SmallVector<TemplateArgument, 16> &TemplateArgs);
+                                  SourceLocation *TemplateArgLocsIn,
+                        llvm::SmallVector<TemplateArgumentLoc, 16> &TempArgs);
     
   QualType CheckTemplateIdType(TemplateName Template,
                                SourceLocation TemplateLoc,
                                SourceLocation LAngleLoc,
-                               const TemplateArgument *TemplateArgs,
+                               const TemplateArgumentLoc *TemplateArgs,
                                unsigned NumTemplateArgs,
                                SourceLocation RAngleLoc);
 
@@ -2532,7 +2533,7 @@
                                        TemplateName Template,
                                        SourceLocation TemplateNameLoc,
                                        SourceLocation LAngleLoc,
-                                       const TemplateArgument *TemplateArgs,
+                                       const TemplateArgumentLoc *TemplateArgs,
                                        unsigned NumTemplateArgs,
                                        SourceLocation RAngleLoc);
 
@@ -2587,7 +2588,7 @@
   bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
                                            bool HasExplicitTemplateArgs,
                                            SourceLocation LAngleLoc,
-                                  const TemplateArgument *ExplicitTemplateArgs,
+                            const TemplateArgumentLoc *ExplicitTemplateArgs,
                                            unsigned NumExplicitTemplateArgs,
                                            SourceLocation RAngleLoc,
                                            NamedDecl *&PrevDecl);
@@ -2627,18 +2628,18 @@
   bool CheckTemplateArgumentList(TemplateDecl *Template,
                                  SourceLocation TemplateLoc,
                                  SourceLocation LAngleLoc,
-                                 const TemplateArgument *TemplateArgs,
+                                 const TemplateArgumentLoc *TemplateArgs,
                                  unsigned NumTemplateArgs,
                                  SourceLocation RAngleLoc,
                                  bool PartialTemplateArgs,
                                  TemplateArgumentListBuilder &Converted);
 
   bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
-                                 const TemplateArgument &Arg,
+                                 const TemplateArgumentLoc &Arg,
                                  TemplateArgumentListBuilder &Converted);
 
-  bool CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg,
-                             SourceLocation ArgLoc);
+  bool CheckTemplateArgument(TemplateTypeParmDecl *Param,
+                             DeclaratorInfo *Arg);
   bool CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,
                                                       NamedDecl *&Entity);
   bool CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member);
@@ -2813,7 +2814,7 @@
 
   TemplateDeductionResult
   SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
-                                const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                       unsigned NumExplicitTemplateArgs,
                             llvm::SmallVectorImpl<TemplateArgument> &Deduced,
                                  llvm::SmallVectorImpl<QualType> &ParamTypes,
@@ -2829,7 +2830,7 @@
   TemplateDeductionResult
   DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
                           bool HasExplicitTemplateArgs,
-                          const TemplateArgument *ExplicitTemplateArgs,
+                          const TemplateArgumentLoc *ExplicitTemplateArgs,
                           unsigned NumExplicitTemplateArgs,
                           Expr **Args, unsigned NumArgs,
                           FunctionDecl *&Specialization,
@@ -2838,7 +2839,7 @@
   TemplateDeductionResult
   DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
                           bool HasExplicitTemplateArgs,
-                          const TemplateArgument *ExplicitTemplateArgs,
+                          const TemplateArgumentLoc *ExplicitTemplateArgs,
                           unsigned NumExplicitTemplateArgs,
                           QualType ArgFunctionType,
                           FunctionDecl *&Specialization,
@@ -3220,8 +3221,8 @@
   TemplateName
   SubstTemplateName(TemplateName Name, SourceLocation Loc,
                     const MultiLevelTemplateArgumentList &TemplateArgs);
-  TemplateArgument Subst(TemplateArgument Arg,
-                         const MultiLevelTemplateArgumentList &TemplateArgs);
+  bool Subst(const TemplateArgumentLoc &Arg, TemplateArgumentLoc &Result,
+             const MultiLevelTemplateArgumentList &TemplateArgs);
 
   void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
                                      FunctionDecl *Function,
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index b877b1c..9e4bb35 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1234,7 +1234,7 @@
   SourceRange QualifierRange;
   bool ArgumentDependentLookup;
   bool HasExplicitTemplateArgs;
-  const TemplateArgument *ExplicitTemplateArgs;
+  const TemplateArgumentLoc *ExplicitTemplateArgs;
   unsigned NumExplicitTemplateArgs;
   
   DeconstructCallFunction(Fn,
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index a868579..2ba1130 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2796,7 +2796,7 @@
   // If the declarator is a template-id, translate the parser's template 
   // argument list into our AST format.
   bool HasExplicitTemplateArgs = false;
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   SourceLocation LAngleLoc, RAngleLoc;
   if (D.getKind() == Declarator::DK_TemplateId) {
     TemplateIdAnnotation *TemplateId = D.getTemplateId();
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index a322eb0..aa28610 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -1959,7 +1959,7 @@
                                DeclarationName MemberName,
                                bool HasExplicitTemplateArgs,
                                SourceLocation LAngleLoc,
-                               const TemplateArgument *ExplicitTemplateArgs,
+                               const TemplateArgumentLoc *ExplicitTemplateArgs,
                                unsigned NumExplicitTemplateArgs,
                                SourceLocation RAngleLoc,
                                DeclPtrTy ObjCImpDecl, const CXXScopeSpec *SS,
@@ -2711,7 +2711,7 @@
                                    SourceRange &QualifierRange,
                                    bool &ArgumentDependentLookup,
                                    bool &HasExplicitTemplateArguments,
-                                 const TemplateArgument *&ExplicitTemplateArgs,
+                           const TemplateArgumentLoc *&ExplicitTemplateArgs,
                                    unsigned &NumExplicitTemplateArgs) {
   // Set defaults for all of the output parameters.
   Function = 0;
@@ -2892,7 +2892,7 @@
   // lookup and whether there were any explicitly-specified template arguments.
   bool ADL = true;
   bool HasExplicitTemplateArgs = 0;
-  const TemplateArgument *ExplicitTemplateArgs = 0;
+  const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
   unsigned NumExplicitTemplateArgs = 0;
   NestedNameSpecifier *Qualifier = 0;
   SourceRange QualifierRange;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index d5f93dc..32eeddb 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -2191,7 +2191,7 @@
                              TypeTy *T,
                              const CXXScopeSpec &SS,
                              bool HasTrailingLParen) {
-  QualType Type = QualType::getFromOpaquePtr(T);
+  QualType Type = GetTypeFromParser(T);
   CanQualType CanType = Context.getCanonicalType(Type);
   DeclarationName DtorName =
     Context.DeclarationNames.getCXXDestructorName(CanType);
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 40e1450..150f4ae 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -2444,7 +2444,7 @@
 void
 Sema::AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl,
                                  bool HasExplicitTemplateArgs,
-                                 const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                  unsigned NumExplicitTemplateArgs,
                                  Expr *Object, Expr **Args, unsigned NumArgs,
                                  OverloadCandidateSet& CandidateSet,
@@ -2489,7 +2489,7 @@
 void
 Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate,
                                    bool HasExplicitTemplateArgs,
-                                 const TemplateArgument *ExplicitTemplateArgs,
+                          const TemplateArgumentLoc *ExplicitTemplateArgs,
                                    unsigned NumExplicitTemplateArgs,
                                    Expr **Args, unsigned NumArgs,
                                    OverloadCandidateSet& CandidateSet,
@@ -3886,7 +3886,7 @@
 Sema::AddArgumentDependentLookupCandidates(DeclarationName Name,
                                            Expr **Args, unsigned NumArgs,
                                            bool HasExplicitTemplateArgs,
-                                const TemplateArgument *ExplicitTemplateArgs,
+                            const TemplateArgumentLoc *ExplicitTemplateArgs,
                                            unsigned NumExplicitTemplateArgs,                                            
                                            OverloadCandidateSet& CandidateSet,
                                            bool PartialOverloading) {
@@ -4278,7 +4278,7 @@
   }
 
   bool HasExplicitTemplateArgs = false;
-  const TemplateArgument *ExplicitTemplateArgs = 0;
+  const TemplateArgumentLoc *ExplicitTemplateArgs = 0;
   unsigned NumExplicitTemplateArgs = 0;
   
   // Try to dig out the overloaded function.
@@ -4451,7 +4451,7 @@
                                        AnyFunctionDecl Callee,
                                        bool &ArgumentDependentLookup,
                                        bool HasExplicitTemplateArgs,
-                                 const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                        unsigned NumExplicitTemplateArgs,
                                        Expr **Args, unsigned NumArgs,
                                        OverloadCandidateSet &CandidateSet,
@@ -4483,7 +4483,7 @@
                                        DeclarationName &UnqualifiedName,
                                        bool &ArgumentDependentLookup,
                                        bool HasExplicitTemplateArgs,
-                                  const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                        unsigned NumExplicitTemplateArgs,
                                        Expr **Args, unsigned NumArgs,
                                        OverloadCandidateSet &CandidateSet,
@@ -4551,7 +4551,7 @@
 FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee,
                                             DeclarationName UnqualifiedName,
                                             bool HasExplicitTemplateArgs,
-                                 const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                             unsigned NumExplicitTemplateArgs,
                                             SourceLocation LParenLoc,
                                             Expr **Args, unsigned NumArgs,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 36a158d..a2883fa 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -321,8 +321,11 @@
                                      TypeTy *DefaultT) {
   TemplateTypeParmDecl *Parm
     = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>());
-  // FIXME: Preserve type source info.
-  QualType Default = GetTypeFromParser(DefaultT);
+
+  DeclaratorInfo *DefaultDInfo;
+  GetTypeFromParser(DefaultT, &DefaultDInfo);
+
+  assert(DefaultDInfo && "expected source information for type");
 
   // C++0x [temp.param]p9:
   // A default template-argument may be specified for any kind of
@@ -337,12 +340,12 @@
   // FIXME: Implement this check! Needs a recursive walk over the types.
 
   // Check the template argument itself.
-  if (CheckTemplateArgument(Parm, Default, DefaultLoc)) {
+  if (CheckTemplateArgument(Parm, DefaultDInfo)) {
     Parm->setInvalidDecl();
     return;
   }
 
-  Parm->setDefaultArgument(Default, DefaultLoc, false);
+  Parm->setDefaultArgument(DefaultDInfo, false);
 }
 
 /// \brief Check that the type of a non-type template parameter is
@@ -843,7 +846,7 @@
         SawParameterPack = true;
         ParameterPackLoc = NewTypeParm->getLocation();
       } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() &&
-          NewTypeParm->hasDefaultArgument()) {
+                 NewTypeParm->hasDefaultArgument()) {
         OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc();
         NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc();
         SawDefaultArgument = true;
@@ -853,8 +856,7 @@
         // Merge the default argument from the old declaration to the
         // new declaration.
         SawDefaultArgument = true;
-        NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgument(),
-                                        OldTypeParm->getDefaultArgumentLoc(),
+        NewTypeParm->setDefaultArgument(OldTypeParm->getDefaultArgumentInfo(),
                                         true);
         PreviousDefaultArgLoc = OldTypeParm->getDefaultArgumentLoc();
       } else if (NewTypeParm->hasDefaultArgument()) {
@@ -1096,24 +1098,28 @@
 /// into template arguments used by semantic analysis.
 void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
                                       SourceLocation *TemplateArgLocs,
-                     llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) {
+                  llvm::SmallVector<TemplateArgumentLoc, 16> &TemplateArgs) {
   TemplateArgs.reserve(TemplateArgsIn.size());
 
   void **Args = TemplateArgsIn.getArgs();
   bool *ArgIsType = TemplateArgsIn.getArgIsType();
   for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
-    TemplateArgs.push_back(
-      ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg],
-                                       //FIXME: Preserve type source info.
-                                       Sema::GetTypeFromParser(Args[Arg]))
-                    : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg])));
+    if (ArgIsType[Arg]) {
+      DeclaratorInfo *DI;
+      QualType T = Sema::GetTypeFromParser(Args[Arg], &DI);
+      if (!DI) DI = Context.getTrivialDeclaratorInfo(T, TemplateArgLocs[Arg]);
+      TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
+    } else {
+      Expr *E = reinterpret_cast<Expr *>(Args[Arg]);
+      TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
+    }
   }
 }
 
 QualType Sema::CheckTemplateIdType(TemplateName Name,
                                    SourceLocation TemplateLoc,
                                    SourceLocation LAngleLoc,
-                                   const TemplateArgument *TemplateArgs,
+                                   const TemplateArgumentLoc *TemplateArgs,
                                    unsigned NumTemplateArgs,
                                    SourceLocation RAngleLoc) {
   TemplateDecl *Template = Name.getAsTemplateDecl();
@@ -1155,7 +1161,7 @@
                                                    Converted.flatSize());
 
     // FIXME: CanonType is not actually the canonical type, and unfortunately
-    // it is a TemplateTypeSpecializationType that we will never use again.
+    // it is a TemplateSpecializationType that we will never use again.
     // In the future, we need to teach getTemplateSpecializationType to only
     // build the canonical type and return that to us.
     CanonType = Context.getCanonicalType(CanonType);
@@ -1190,7 +1196,6 @@
   // Build the fully-sugared type for this class template
   // specialization, which refers back to the class template
   // specialization we created or found.
-  //FIXME: Preserve type source info.
   return Context.getTemplateSpecializationType(Name, TemplateArgs,
                                                NumTemplateArgs, CanonType);
 }
@@ -1199,13 +1204,13 @@
 Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc,
                           SourceLocation LAngleLoc,
                           ASTTemplateArgsPtr TemplateArgsIn,
-                          SourceLocation *TemplateArgLocs,
+                          SourceLocation *TemplateArgLocsIn,
                           SourceLocation RAngleLoc) {
   TemplateName Template = TemplateD.getAsVal<TemplateName>();
 
   // Translate the parser's template argument list in our AST format.
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
-  translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+  translateTemplateArguments(TemplateArgsIn, TemplateArgLocsIn, TemplateArgs);
 
   QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc,
                                         TemplateArgs.data(),
@@ -1216,7 +1221,16 @@
   if (Result.isNull())
     return true;
 
-  return Result.getAsOpaquePtr();
+  DeclaratorInfo *DI = Context.CreateDeclaratorInfo(Result);
+  TemplateSpecializationTypeLoc TL
+    = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc());
+  TL.setTemplateNameLoc(TemplateLoc);
+  TL.setLAngleLoc(LAngleLoc);
+  TL.setRAngleLoc(RAngleLoc);
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
+    TL.setArgLocInfo(i, TemplateArgs[i].getLocInfo());
+
+  return CreateLocInfoType(Result, DI).getAsOpaquePtr();
 }
 
 Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,
@@ -1226,7 +1240,9 @@
   if (TypeResult.isInvalid())
     return Sema::TypeResult();
 
-  QualType Type = QualType::getFromOpaquePtr(TypeResult.get());
+  // FIXME: preserve source info, ideally without copying the DI.
+  DeclaratorInfo *DI;
+  QualType Type = GetTypeFromParser(TypeResult.get(), &DI);
 
   // Verify the tag specifier.
   TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec);
@@ -1256,7 +1272,7 @@
                                                  TemplateName Template,
                                                  SourceLocation TemplateNameLoc,
                                                  SourceLocation LAngleLoc,
-                                           const TemplateArgument *TemplateArgs,
+                                        const TemplateArgumentLoc *TemplateArgs,
                                                  unsigned NumTemplateArgs,
                                                  SourceLocation RAngleLoc) {
   // FIXME: Can we do any checking at this point? I guess we could check the
@@ -1296,13 +1312,13 @@
                                                  SourceLocation TemplateNameLoc,
                                                  SourceLocation LAngleLoc,
                                               ASTTemplateArgsPtr TemplateArgsIn,
-                                                SourceLocation *TemplateArgLocs,
+                                                SourceLocation *TemplateArgSLs,
                                                  SourceLocation RAngleLoc) {
   TemplateName Template = TemplateD.getAsVal<TemplateName>();
 
   // Translate the parser's template argument list in our AST format.
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
-  translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
+  translateTemplateArguments(TemplateArgsIn, TemplateArgSLs, TemplateArgs);
   TemplateArgsIn.release();
 
   return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(),
@@ -1336,7 +1352,7 @@
     Name = Template.getAsDependentTemplateName()->getName();
 
   // Translate the parser's template argument list in our AST format.
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
   TemplateArgsIn.release();
 
@@ -1397,8 +1413,10 @@
 }
 
 bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
-                                     const TemplateArgument &Arg,
+                                     const TemplateArgumentLoc &AL,
                                      TemplateArgumentListBuilder &Converted) {
+  const TemplateArgument &Arg = AL.getArgument();
+
   // Check template type parameter.
   if (Arg.getKind() != TemplateArgument::Type) {
     // C++ [temp.arg.type]p1:
@@ -1407,19 +1425,18 @@
 
     // We have a template type parameter but the template argument
     // is not a type.
-    Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
+    Diag(AL.getLocation(), diag::err_template_arg_must_be_type);
     Diag(Param->getLocation(), diag::note_template_param_here);
 
     return true;
   }
 
-  if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation()))
+  if (CheckTemplateArgument(Param, AL.getSourceDeclaratorInfo()))
     return true;
 
   // Add the converted template type argument.
   Converted.Append(
-                 TemplateArgument(Arg.getLocation(),
-                                  Context.getCanonicalType(Arg.getAsType())));
+                 TemplateArgument(Context.getCanonicalType(Arg.getAsType())));
   return false;
 }
 
@@ -1428,7 +1445,7 @@
 bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
                                      SourceLocation TemplateLoc,
                                      SourceLocation LAngleLoc,
-                                     const TemplateArgument *TemplateArgs,
+                                     const TemplateArgumentLoc *TemplateArgs,
                                      unsigned NumTemplateArgs,
                                      SourceLocation RAngleLoc,
                                      bool PartialTemplateArgs,
@@ -1474,7 +1491,8 @@
       break;
 
     // Decode the template argument
-    TemplateArgument Arg;
+    TemplateArgumentLoc Arg;
+
     if (ArgIdx >= NumArgs) {
       // Retrieve the default template argument from the template
       // parameter.
@@ -1489,11 +1507,11 @@
         if (!TTP->hasDefaultArgument())
           break;
 
-        QualType ArgType = TTP->getDefaultArgument();
+        DeclaratorInfo *ArgType = TTP->getDefaultArgumentInfo();
 
         // If the argument type is dependent, instantiate it now based
         // on the previously-computed template arguments.
-        if (ArgType->isDependentType()) {
+        if (ArgType->getType()->isDependentType()) {
           InstantiatingTemplate Inst(*this, TemplateLoc,
                                      Template, Converted.getFlatArguments(),
                                      Converted.flatSize(),
@@ -1507,10 +1525,10 @@
                               TTP->getDeclName());
         }
 
-        if (ArgType.isNull())
+        if (!ArgType)
           return true;
 
-        Arg = TemplateArgument(TTP->getLocation(), ArgType);
+        Arg = TemplateArgumentLoc(TemplateArgument(ArgType->getType()), ArgType);
       } else if (NonTypeTemplateParmDecl *NTTP
                    = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
         if (!NTTP->hasDefaultArgument())
@@ -1530,7 +1548,8 @@
         if (E.isInvalid())
           return true;
 
-        Arg = TemplateArgument(E.takeAs<Expr>());
+        Expr *Ex = E.takeAs<Expr>();
+        Arg = TemplateArgumentLoc(TemplateArgument(Ex), Ex);
       } else {
         TemplateTemplateParmDecl *TempParm
           = cast<TemplateTemplateParmDecl>(*Param);
@@ -1539,7 +1558,8 @@
           break;
 
         // FIXME: Subst default argument
-        Arg = TemplateArgument(TempParm->getDefaultArgument());
+        // FIXME: preserve source information
+        Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()));
       }
     } else {
       // Retrieve the template argument produced by the user.
@@ -1592,13 +1612,13 @@
         }
       }
 
-      switch (Arg.getKind()) {
+      switch (Arg.getArgument().getKind()) {
       case TemplateArgument::Null:
         assert(false && "Should never see a NULL template argument here");
         break;
 
       case TemplateArgument::Expression: {
-        Expr *E = Arg.getAsExpr();
+        Expr *E = Arg.getArgument().getAsExpr();
         TemplateArgument Result;
         if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
           Invalid = true;
@@ -1611,10 +1631,10 @@
       case TemplateArgument::Integral:
         // We've already checked this template argument, so just copy
         // it to the list of converted arguments.
-        Converted.Append(Arg);
+        Converted.Append(Arg.getArgument());
         break;
 
-      case TemplateArgument::Type:
+      case TemplateArgument::Type: {
         // We have a non-type template parameter but the template
         // argument is a type.
 
@@ -1625,14 +1645,16 @@
         //
         // We warn specifically about this case, since it can be rather
         // confusing for users.
-        if (Arg.getAsType()->isFunctionType())
+        QualType T = Arg.getArgument().getAsType();
+        if (T->isFunctionType())
           Diag(Arg.getLocation(), diag::err_template_arg_nontype_ambig)
-            << Arg.getAsType();
+            << T;
         else
           Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr);
         Diag((*Param)->getLocation(), diag::note_template_param_here);
         Invalid = true;
         break;
+      }
 
       case TemplateArgument::Pack:
         assert(0 && "FIXME: Implement!");
@@ -1643,13 +1665,13 @@
       TemplateTemplateParmDecl *TempParm
         = cast<TemplateTemplateParmDecl>(*Param);
 
-      switch (Arg.getKind()) {
+      switch (Arg.getArgument().getKind()) {
       case TemplateArgument::Null:
         assert(false && "Should never see a NULL template argument here");
         break;
 
       case TemplateArgument::Expression: {
-        Expr *ArgExpr = Arg.getAsExpr();
+        Expr *ArgExpr = Arg.getArgument().getAsExpr();
         if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
             isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
           if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
@@ -1658,7 +1680,7 @@
           // Add the converted template argument.
           Decl *D
             = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl();
-          Converted.Append(TemplateArgument(Arg.getLocation(), D));
+          Converted.Append(TemplateArgument(D));
           continue;
         }
       }
@@ -1675,7 +1697,7 @@
       case TemplateArgument::Declaration:
         // We've already checked this template argument, so just copy
         // it to the list of converted arguments.
-        Converted.Append(Arg);
+        Converted.Append(Arg.getArgument());
         break;
 
       case TemplateArgument::Integral:
@@ -1698,7 +1720,10 @@
 /// This routine implements the semantics of C++ [temp.arg.type]. It
 /// returns true if an error occurred, and false otherwise.
 bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param,
-                                 QualType Arg, SourceLocation ArgLoc) {
+                                 DeclaratorInfo *ArgInfo) {
+  assert(ArgInfo && "invalid DeclaratorInfo");
+  QualType Arg = ArgInfo->getType();
+
   // C++ [temp.arg.type]p2:
   //   A local type, a type with no linkage, an unnamed type or a type
   //   compounded from any of these types shall not be used as a
@@ -1710,12 +1735,14 @@
     Tag = EnumT;
   else if (const RecordType *RecordT = Arg->getAs<RecordType>())
     Tag = RecordT;
-  if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod())
-    return Diag(ArgLoc, diag::err_template_arg_local_type)
-      << QualType(Tag, 0);
-  else if (Tag && !Tag->getDecl()->getDeclName() &&
+  if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) {
+    SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+    return Diag(SR.getBegin(), diag::err_template_arg_local_type)
+      << QualType(Tag, 0) << SR;
+  } else if (Tag && !Tag->getDecl()->getDeclName() &&
            !Tag->getDecl()->getTypedefForAnonDecl()) {
-    Diag(ArgLoc, diag::err_template_arg_unnamed_type);
+    SourceRange SR = ArgInfo->getTypeLoc().getFullSourceRange();
+    Diag(SR.getBegin(), diag::err_template_arg_unnamed_type) << SR;
     Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here);
     return true;
   }
@@ -2015,7 +2042,7 @@
       return false;
     }
 
-    Converted = TemplateArgument(StartLoc, Value,
+    Converted = TemplateArgument(Value,
                                  ParamType->isEnumeralType() ? ParamType
                                                              : IntegerType);
     return false;
@@ -2089,7 +2116,7 @@
 
       if (Member)
         Member = cast<NamedDecl>(Member->getCanonicalDecl());
-      Converted = TemplateArgument(StartLoc, Member);
+      Converted = TemplateArgument(Member);
       return false;
     }
 
@@ -2099,7 +2126,7 @@
 
     if (Entity)
       Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(StartLoc, Entity);
+    Converted = TemplateArgument(Entity);
     return false;
   }
 
@@ -2139,7 +2166,7 @@
 
     if (Entity)
       Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(StartLoc, Entity);
+    Converted = TemplateArgument(Entity);
     return false;
   }
 
@@ -2180,7 +2207,7 @@
       return true;
 
     Entity = cast<NamedDecl>(Entity->getCanonicalDecl());
-    Converted = TemplateArgument(StartLoc, Entity);
+    Converted = TemplateArgument(Entity);
     return false;
   }
 
@@ -2210,7 +2237,7 @@
 
   if (Member)
     Member = cast<NamedDecl>(Member->getCanonicalDecl());
-  Converted = TemplateArgument(StartLoc, Member);
+  Converted = TemplateArgument(Member);
   return false;
 }
 
@@ -2722,7 +2749,7 @@
         if (TTP->hasDefaultArgument()) {
           Diag(TTP->getDefaultArgumentLoc(),
                diag::err_default_arg_in_partial_spec);
-          TTP->setDefaultArgument(QualType(), SourceLocation(), false);
+          TTP->removeDefaultArgument();
         }
       } else if (NonTypeTemplateParmDecl *NTTP
                    = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
@@ -2781,7 +2808,7 @@
   }
 
   // Translate the parser's template argument list in our AST format.
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
 
   // Check that the template argument list is well-formed for this
@@ -2889,6 +2916,8 @@
                                                        TemplateParams,
                                                        ClassTemplate,
                                                        Converted,
+                                                       TemplateArgs.data(),
+                                                       TemplateArgs.size(),
                                                        PrevPartial);
 
     if (PrevPartial) {
@@ -3268,7 +3297,7 @@
 Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
                                           bool HasExplicitTemplateArgs,
                                           SourceLocation LAngleLoc,
-                              const TemplateArgument *ExplicitTemplateArgs,
+                           const TemplateArgumentLoc *ExplicitTemplateArgs,
                                           unsigned NumExplicitTemplateArgs,
                                           SourceLocation RAngleLoc,
                                           NamedDecl *&PrevDecl) {
@@ -3624,7 +3653,7 @@
                            : TSK_ExplicitInstantiationDeclaration;
   
   // Translate the parser's template argument list in our AST format.
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
 
   // Check that the template argument list is well-formed for this
@@ -4003,7 +4032,7 @@
   // If the declarator is a template-id, translate the parser's template 
   // argument list into our AST format.
   bool HasExplicitTemplateArgs = false;
-  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs;
   if (D.getKind() == Declarator::DK_TemplateId) {
     TemplateIdAnnotation *TemplateId = D.getTemplateId();
     ASTTemplateArgsPtr TemplateArgsPtr(*this,
@@ -4310,25 +4339,13 @@
     /// refers to a member of the current instantiation, and then
     /// type-checking and building a QualifiedNameType (when possible).
     QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL);
-    QualType TransformTypenameType(TypenameType *T);
   };
 }
 
 QualType
 CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB,
                                                      TypenameTypeLoc TL) {
-  QualType Result = TransformTypenameType(TL.getTypePtr());
-  if (Result.isNull())
-    return QualType();
-
-  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
-
-  return Result;
-}
-
-QualType
-CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) {
+  TypenameType *T = TL.getTypePtr();
 
   NestedNameSpecifier *NNS
     = TransformNestedNameSpecifier(T->getQualifier(),
@@ -4342,12 +4359,14 @@
   CXXScopeSpec SS;
   SS.setRange(SourceRange(getBaseLocation()));
   SS.setScopeRep(NNS);
+
+  QualType Result;
   if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0)
-    return QualType(T, 0);
+    Result = QualType(T, 0);
 
   // Rebuild the typename type, which will probably turn into a
   // QualifiedNameType.
-  if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
+  else if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {
     QualType NewTemplateId
       = TransformType(QualType(TemplateId, 0));
     if (NewTemplateId.isNull())
@@ -4355,12 +4374,16 @@
 
     if (NNS == T->getQualifier() &&
         NewTemplateId == QualType(TemplateId, 0))
-      return QualType(T, 0);
+      Result = QualType(T, 0);
+    else
+      Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
+  } else
+    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(),
+                                              SourceRange(TL.getNameLoc()));
 
-    return getDerived().RebuildTypenameType(NNS, NewTemplateId);
-  }
-
-  return getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result);
+  NewTL.setNameLoc(TL.getNameLoc());
+  return Result;
 }
 
 /// \brief Rebuilds a type within the context of the current instantiation.
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 14373de..7b5ad7f 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -90,7 +90,7 @@
       Value.extOrTrunc(AllowedBits);
     Value.setIsSigned(T->isSignedIntegerType());
 
-    Deduced[NTTP->getIndex()] = TemplateArgument(SourceLocation(), Value, T);
+    Deduced[NTTP->getIndex()] = TemplateArgument(Value, T);
     return Sema::TDK_Success;
   }
 
@@ -102,7 +102,7 @@
   if (PrevValuePtr->isNegative()) {
     Info.Param = NTTP;
     Info.FirstArg = Deduced[NTTP->getIndex()];
-    Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
+    Info.SecondArg = TemplateArgument(Value, NTTP->getType());
     return Sema::TDK_Inconsistent;
   }
 
@@ -115,7 +115,7 @@
   if (Value != PrevValue) {
     Info.Param = NTTP;
     Info.FirstArg = Deduced[NTTP->getIndex()];
-    Info.SecondArg = TemplateArgument(SourceLocation(), Value, NTTP->getType());
+    Info.SecondArg = TemplateArgument(Value, NTTP->getType());
     return Sema::TDK_Inconsistent;
   }
 
@@ -433,7 +433,7 @@
     if (Param.isMoreQualifiedThan(Arg) && !(TDF & TDF_IgnoreQualifiers)) {
       Info.Param = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
       Info.FirstArg = Deduced[Index];
-      Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+      Info.SecondArg = TemplateArgument(Arg);
       return Sema::TDK_InconsistentQuals;
     }
 
@@ -445,7 +445,7 @@
       DeducedType = Context.getCanonicalType(DeducedType);
 
     if (Deduced[Index].isNull())
-      Deduced[Index] = TemplateArgument(SourceLocation(), DeducedType);
+      Deduced[Index] = TemplateArgument(DeducedType);
     else {
       // C++ [temp.deduct.type]p2:
       //   [...] If type deduction cannot be done for any P/A pair, or if for
@@ -457,7 +457,7 @@
         Info.Param
           = cast<TemplateTypeParmDecl>(TemplateParams->getParam(Index));
         Info.FirstArg = Deduced[Index];
-        Info.SecondArg = TemplateArgument(SourceLocation(), Arg);
+        Info.SecondArg = TemplateArgument(Arg);
         return Sema::TDK_Inconsistent;
       }
     }
@@ -465,8 +465,8 @@
   }
 
   // Set up the template argument deduction information for a failure.
-  Info.FirstArg = TemplateArgument(SourceLocation(), ParamIn);
-  Info.SecondArg = TemplateArgument(SourceLocation(), ArgIn);
+  Info.FirstArg = TemplateArgument(ParamIn);
+  Info.SecondArg = TemplateArgument(ArgIn);
 
   // Check the cv-qualifiers on the parameter and argument types.
   if (!(TDF & TDF_IgnoreQualifiers)) {
@@ -982,18 +982,41 @@
   // and are equivalent to the template arguments originally provided
   // to the class template.
   ClassTemplateDecl *ClassTemplate = Partial->getSpecializedTemplate();
-  const TemplateArgumentList &PartialTemplateArgs = Partial->getTemplateArgs();
-  for (unsigned I = 0, N = PartialTemplateArgs.flat_size(); I != N; ++I) {
+  const TemplateArgumentLoc *PartialTemplateArgs
+    = Partial->getTemplateArgsAsWritten();
+  unsigned N = Partial->getNumTemplateArgsAsWritten();
+  llvm::SmallVector<TemplateArgumentLoc, 16> InstArgs(N);
+  for (unsigned I = 0; I != N; ++I) {
     Decl *Param = const_cast<NamedDecl *>(
                     ClassTemplate->getTemplateParameters()->getParam(I));
-    TemplateArgument InstArg
-      = Subst(PartialTemplateArgs[I],
-              MultiLevelTemplateArgumentList(*DeducedArgumentList));
-    if (InstArg.isNull()) {
+    if (Subst(PartialTemplateArgs[I], InstArgs[I],
+              MultiLevelTemplateArgumentList(*DeducedArgumentList))) {
       Info.Param = makeTemplateParameter(Param);
-      Info.FirstArg = PartialTemplateArgs[I];
+      Info.FirstArg = PartialTemplateArgs[I].getArgument();
       return TDK_SubstitutionFailure;
     }
+  }
+
+  TemplateArgumentListBuilder ConvertedInstArgs(
+                                  ClassTemplate->getTemplateParameters(), N);
+
+  if (CheckTemplateArgumentList(ClassTemplate, Partial->getLocation(),
+                                /*LAngle*/ SourceLocation(),
+                                InstArgs.data(), N,
+                                /*RAngle*/ SourceLocation(),
+                                false, ConvertedInstArgs)) {
+    // FIXME: fail with more useful information?
+    return TDK_SubstitutionFailure;
+  }
+  
+  for (unsigned I = 0, E = ConvertedInstArgs.flatSize(); I != E; ++I) {
+    // We don't really care if we overwrite the internal structures of
+    // the arg list builder, because we're going to throw it all away.
+    TemplateArgument &InstArg
+      = const_cast<TemplateArgument&>(ConvertedInstArgs.getFlatArguments()[I]);
+
+    Decl *Param = const_cast<NamedDecl *>(
+                    ClassTemplate->getTemplateParameters()->getParam(I));
 
     if (InstArg.getKind() == TemplateArgument::Expression) {
       // When the argument is an expression, check the expression result
@@ -1004,7 +1027,7 @@
             = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
         if (CheckTemplateArgument(NTTP, NTTP->getType(), InstExpr, InstArg)) {
           Info.Param = makeTemplateParameter(Param);
-          Info.FirstArg = PartialTemplateArgs[I];
+          Info.FirstArg = Partial->getTemplateArgs()[I];
           return TDK_SubstitutionFailure;
         }
       } else if (TemplateTemplateParmDecl *TTP
@@ -1013,7 +1036,7 @@
         DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
         if (!DRE || CheckTemplateArgument(TTP, DRE)) {
           Info.Param = makeTemplateParameter(Param);
-          Info.FirstArg = PartialTemplateArgs[I];
+          Info.FirstArg = Partial->getTemplateArgs()[I];
           return TDK_SubstitutionFailure;
         }
       }
@@ -1072,7 +1095,7 @@
 Sema::TemplateDeductionResult
 Sema::SubstituteExplicitTemplateArguments(
                                       FunctionTemplateDecl *FunctionTemplate,
-                                const TemplateArgument *ExplicitTemplateArgs,
+                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                           unsigned NumExplicitTemplateArgs,
                             llvm::SmallVectorImpl<TemplateArgument> &Deduced,
                                  llvm::SmallVectorImpl<QualType> &ParamTypes,
@@ -1290,7 +1313,7 @@
 Sema::TemplateDeductionResult
 Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
                               bool HasExplicitTemplateArgs,
-                              const TemplateArgument *ExplicitTemplateArgs,
+                              const TemplateArgumentLoc *ExplicitTemplateArgs,
                               unsigned NumExplicitTemplateArgs,
                               Expr **Args, unsigned NumArgs,
                               FunctionDecl *&Specialization,
@@ -1460,7 +1483,7 @@
 Sema::TemplateDeductionResult
 Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
                               bool HasExplicitTemplateArgs,
-                              const TemplateArgument *ExplicitTemplateArgs,
+                              const TemplateArgumentLoc *ExplicitTemplateArgs,
                               unsigned NumExplicitTemplateArgs,
                               QualType ArgFunctionType,
                               FunctionDecl *&Specialization,
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 794ec2a..8fab8f6 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1261,9 +1261,10 @@
   return Instantiator.TransformTemplateName(Name);
 }
 
-TemplateArgument Sema::Subst(TemplateArgument Arg,
-                         const MultiLevelTemplateArgumentList &TemplateArgs) {
+bool Sema::Subst(const TemplateArgumentLoc &Input, TemplateArgumentLoc &Output,
+                 const MultiLevelTemplateArgumentList &TemplateArgs) {
   TemplateInstantiator Instantiator(*this, TemplateArgs, SourceLocation(),
                                     DeclarationName());
-  return Instantiator.TransformTemplateArgument(Arg);
+
+  return Instantiator.TransformTemplateArgument(Input, Output);
 }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 50b0fb8..0b54533 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -886,14 +886,13 @@
   // FIXME: Do we actually want to perform substitution here? I don't think
   // we do.
   if (D->hasDefaultArgument()) {
-    QualType DefaultPattern = D->getDefaultArgument();
-    QualType DefaultInst
+    DeclaratorInfo *DefaultPattern = D->getDefaultArgumentInfo();
+    DeclaratorInfo *DefaultInst
       = SemaRef.SubstType(DefaultPattern, TemplateArgs,
                           D->getDefaultArgumentLoc(),
                           D->getDeclName());
 
     Inst->setDefaultArgument(DefaultInst,
-                             D->getDefaultArgumentLoc(),
                              D->defaultArgumentWasInherited() /* preserve? */);
   }
 
@@ -1026,16 +1025,15 @@
   
   // Substitute into the template arguments of the class template partial
   // specialization.
-  const TemplateArgumentList &PartialSpecTemplateArgs 
-    = PartialSpec->getTemplateInstantiationArgs();
-  llvm::SmallVector<TemplateArgument, 4> InstTemplateArgs;
-  for (unsigned I = 0, N = PartialSpecTemplateArgs.size(); I != N; ++I) {
-    TemplateArgument Inst = SemaRef.Subst(PartialSpecTemplateArgs[I], 
-                                          TemplateArgs);
-    if (Inst.isNull())
+  const TemplateArgumentLoc *PartialSpecTemplateArgs
+    = PartialSpec->getTemplateArgsAsWritten();
+  unsigned N = PartialSpec->getNumTemplateArgsAsWritten();
+
+  llvm::SmallVector<TemplateArgumentLoc, 4> InstTemplateArgs(N);
+  for (unsigned I = 0; I != N; ++I) {
+    if (SemaRef.Subst(PartialSpecTemplateArgs[I], InstTemplateArgs[I],
+                      TemplateArgs))
       return true;
-    
-    InstTemplateArgs.push_back(Inst);
   }
   
 
@@ -1116,6 +1114,8 @@
                                                      InstParams,
                                                      ClassTemplate, 
                                                      Converted,
+                                                     InstTemplateArgs.data(),
+                                                     InstTemplateArgs.size(),
                                                      0);
   InstPartialSpec->setInstantiatedFromMember(PartialSpec);
   InstPartialSpec->setTypeAsWritten(WrittenTy);
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 8e960a4..c135f43 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1328,6 +1328,21 @@
         Visit(TL.getBaseTypeLoc());
       }
     }
+    void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
+      DeclaratorInfo *DInfo = 0;
+      Sema::GetTypeFromParser(DS.getTypeRep(), &DInfo);
+
+      // If we got no declarator info from previous Sema routines,
+      // just fill with the typespec loc.
+      if (!DInfo) {
+        TL.initialize(DS.getTypeSpecTypeLoc());
+        return;
+      }
+
+      TemplateSpecializationTypeLoc OldTL =
+        cast<TemplateSpecializationTypeLoc>(DInfo->getTypeLoc());
+      TL.copy(OldTL);
+    }
     void VisitTypeLoc(TypeLoc TL) {
       // FIXME: add other typespec types and change this to an assert.
       TL.initialize(DS.getTypeSpecTypeLoc());
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index b4ec2fa..5b78375 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -290,7 +290,20 @@
   /// declaration stored within the template argument and constructs a
   /// new template argument from the transformed result. Subclasses may
   /// override this function to provide alternate behavior.
-  TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg);
+  ///
+  /// Returns true if there was an error.
+  bool TransformTemplateArgument(const TemplateArgumentLoc &Input,
+                                 TemplateArgumentLoc &Output);
+
+  /// \brief Fakes up a TemplateArgumentLoc for a given TemplateArgument.
+  void InventTemplateArgumentLoc(const TemplateArgument &Arg,
+                                 TemplateArgumentLoc &ArgLoc);
+
+  /// \brief Fakes up a DeclaratorInfo for a type.
+  DeclaratorInfo *InventDeclaratorInfo(QualType T) {
+    return SemaRef.Context.getTrivialDeclaratorInfo(T,
+                       getDerived().getBaseLocation());
+  }
 
 #define ABSTRACT_TYPELOC(CLASS, PARENT)
 #define TYPELOC(CLASS, PARENT)                                   \
@@ -300,6 +313,11 @@
   QualType 
   TransformTemplateSpecializationType(const TemplateSpecializationType *T,
                                       QualType ObjectType);
+
+  QualType
+  TransformTemplateSpecializationType(TypeLocBuilder &TLB,
+                                      TemplateSpecializationTypeLoc TL,
+                                      QualType ObjectType);
   
   OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);
 
@@ -478,8 +496,11 @@
   /// specialization type. Subclasses may override this routine to provide
   /// different behavior.
   QualType RebuildTemplateSpecializationType(TemplateName Template,
-                                             const TemplateArgument *Args,
-                                             unsigned NumArgs);
+                                             SourceLocation TemplateLoc,
+                                             SourceLocation LAngleLoc,
+                                             const TemplateArgumentLoc *Args,
+                                             unsigned NumArgs,
+                                             SourceLocation RAngleLoc);
 
   /// \brief Build a new qualified name type.
   ///
@@ -509,9 +530,9 @@
   /// (or qualified name type). Subclasses may override this routine to provide
   /// different behavior.
   QualType RebuildTypenameType(NestedNameSpecifier *NNS,
-                               const IdentifierInfo *Id) {
-    return SemaRef.CheckTypenameType(NNS, *Id,
-                                  SourceRange(getDerived().getBaseLocation()));
+                               const IdentifierInfo *Id,
+                               SourceRange SR) {
+    return SemaRef.CheckTypenameType(NNS, *Id, SR);
   }
 
   /// \brief Build a new nested-name-specifier given the prefix and an
@@ -1427,7 +1448,7 @@
                                          TemplateName Template,
                                          SourceLocation TemplateLoc,
                                          SourceLocation LAngleLoc,
-                                         TemplateArgument *TemplateArgs,
+                                         TemplateArgumentLoc *TemplateArgs,
                                          unsigned NumTemplateArgs,
                                          SourceLocation RAngleLoc) {
     return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange,
@@ -1530,7 +1551,7 @@
                                                 SourceLocation TemplateNameLoc,
                                               NamedDecl *FirstQualifierInScope,
                                                   SourceLocation LAngleLoc,
-                                          const TemplateArgument *TemplateArgs,
+                                       const TemplateArgumentLoc *TemplateArgs,
                                                   unsigned NumTemplateArgs,
                                                   SourceLocation RAngleLoc) {
     OwningExprResult Base = move(BaseE);
@@ -1876,30 +1897,67 @@
 }
 
 template<typename Derived>
-TemplateArgument
-TreeTransform<Derived>::TransformTemplateArgument(const TemplateArgument &Arg) {
+void TreeTransform<Derived>::InventTemplateArgumentLoc(
+                                         const TemplateArgument &Arg,
+                                         TemplateArgumentLoc &Output) {
+  SourceLocation Loc = getDerived().getBaseLocation();
+  switch (Arg.getKind()) {
+  case TemplateArgument::Null:
+    llvm::llvm_unreachable("null template argument in TreeTransform");
+    break;
+
+  case TemplateArgument::Type:
+    Output = TemplateArgumentLoc(Arg,
+               SemaRef.Context.getTrivialDeclaratorInfo(Arg.getAsType(), Loc));
+                                            
+    break;
+
+  case TemplateArgument::Expression:
+    Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
+    break;
+
+  case TemplateArgument::Declaration:
+  case TemplateArgument::Integral:
+  case TemplateArgument::Pack:
+    Output = TemplateArgumentLoc(Arg);
+    break;
+  }
+}
+
+template<typename Derived>
+bool TreeTransform<Derived>::TransformTemplateArgument(
+                                         const TemplateArgumentLoc &Input,
+                                         TemplateArgumentLoc &Output) {
+  const TemplateArgument &Arg = Input.getArgument();
   switch (Arg.getKind()) {
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
-    return Arg;
+    Output = Input;
+    return false;
 
   case TemplateArgument::Type: {
-    TemporaryBase Rebase(*this, Arg.getLocation(), DeclarationName());
-    QualType T = getDerived().TransformType(Arg.getAsType());
-    if (T.isNull())
-      return TemplateArgument();
-    return TemplateArgument(Arg.getLocation(), T);
+    DeclaratorInfo *DI = Input.getSourceDeclaratorInfo();
+    if (DI == NULL)
+      DI = InventDeclaratorInfo(Input.getArgument().getAsType());
+
+    DI = getDerived().TransformType(DI);
+    if (!DI) return true;
+
+    Output = TemplateArgumentLoc(TemplateArgument(DI->getType()), DI);
+    return false;
   }
 
   case TemplateArgument::Declaration: {
+    // FIXME: we should never have to transform one of these.
     DeclarationName Name;
     if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
       Name = ND->getDeclName();
-    TemporaryBase Rebase(*this, Arg.getLocation(), Name);
+    TemporaryBase Rebase(*this, SourceLocation(), Name);
     Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
-    if (!D)
-      return TemplateArgument();
-    return TemplateArgument(Arg.getLocation(), D);
+    if (!D) return true;
+
+    Output = TemplateArgumentLoc(TemplateArgument(D));
+    return false;
   }
 
   case TemplateArgument::Expression: {
@@ -1907,10 +1965,16 @@
     EnterExpressionEvaluationContext Unevaluated(getSema(),
                                                  Action::Unevaluated);
 
-    Sema::OwningExprResult E = getDerived().TransformExpr(Arg.getAsExpr());
-    if (E.isInvalid())
-      return TemplateArgument();
-    return TemplateArgument(E.takeAs<Expr>());
+    Expr *InputExpr = Input.getSourceExpression();
+    if (!InputExpr) InputExpr = Input.getArgument().getAsExpr();
+
+    Sema::OwningExprResult E
+      = getDerived().TransformExpr(InputExpr);
+    if (E.isInvalid()) return true;
+
+    Expr *ETaken = E.takeAs<Expr>();
+    Output = TemplateArgumentLoc(TemplateArgument(ETaken), ETaken);
+    return false;
   }
 
   case TemplateArgument::Pack: {
@@ -1919,21 +1983,28 @@
     for (TemplateArgument::pack_iterator A = Arg.pack_begin(),
                                       AEnd = Arg.pack_end();
          A != AEnd; ++A) {
-      TemplateArgument TA = getDerived().TransformTemplateArgument(*A);
-      if (TA.isNull())
-        return TA;
 
-      TransformedArgs.push_back(TA);
+      // FIXME: preserve source information here when we start
+      // caring about parameter packs.
+
+      TemplateArgumentLoc Input;
+      TemplateArgumentLoc Output;
+      getDerived().InventTemplateArgumentLoc(*A, Input);
+      if (getDerived().TransformTemplateArgument(Input, Output))
+        return true;
+
+      TransformedArgs.push_back(Output.getArgument());
     }
     TemplateArgument Result;
     Result.setArgumentPack(TransformedArgs.data(), TransformedArgs.size(),
                            true);
-    return Result;
+    Output = TemplateArgumentLoc(Result);
+    return false;
   }
   }
 
   // Work around bogus GCC warning
-  return TemplateArgument();
+  return true;
 }
 
 //===----------------------------------------------------------------------===//
@@ -2678,46 +2749,74 @@
 TreeTransform<Derived>::TransformTemplateSpecializationType(
                                           TypeLocBuilder &TLB,
                                           TemplateSpecializationTypeLoc TL) {
-  // TODO: figure out how make this work with an ObjectType.
-  QualType Result
-    = TransformTemplateSpecializationType(TL.getTypePtr(), QualType());
-  if (Result.isNull())
-    return QualType();
+  return TransformTemplateSpecializationType(TLB, TL, QualType());
+}
 
-  TemplateSpecializationTypeLoc NewTL
-    = TLB.push<TemplateSpecializationTypeLoc>(Result);
-  NewTL.setNameLoc(TL.getNameLoc());
+template<typename Derived>
+QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
+                                      const TemplateSpecializationType *TST,
+                                                        QualType ObjectType) {
+  // FIXME: this entire method is a temporary workaround; callers
+  // should be rewritten to provide real type locs.
 
-  return Result;
+  // Fake up a TemplateSpecializationTypeLoc.
+  TypeLocBuilder TLB;
+  TemplateSpecializationTypeLoc TL
+    = TLB.push<TemplateSpecializationTypeLoc>(QualType(TST, 0));
+
+  TL.setTemplateNameLoc(getDerived().getBaseLocation());
+  TL.setLAngleLoc(SourceLocation());
+  TL.setRAngleLoc(SourceLocation());
+  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
+    const TemplateArgument &TA = TST->getArg(i);
+    TemplateArgumentLoc TAL;
+    getDerived().InventTemplateArgumentLoc(TA, TAL);
+    TL.setArgLocInfo(i, TAL.getLocInfo());
+  }
+
+  TypeLocBuilder IgnoredTLB;
+  return TransformTemplateSpecializationType(IgnoredTLB, TL, ObjectType);
 }
   
 template<typename Derived>
 QualType TreeTransform<Derived>::TransformTemplateSpecializationType(
-                                        const TemplateSpecializationType *T,
-                                                          QualType ObjectType) {
+                                                        TypeLocBuilder &TLB,
+                                           TemplateSpecializationTypeLoc TL,
+                                                        QualType ObjectType) {
+  const TemplateSpecializationType *T = TL.getTypePtr();
+
   TemplateName Template
     = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);
   if (Template.isNull())
     return QualType();
 
-  llvm::SmallVector<TemplateArgument, 4> NewTemplateArgs;
-  NewTemplateArgs.reserve(T->getNumArgs());
-  for (TemplateSpecializationType::iterator Arg = T->begin(), ArgEnd = T->end();
-       Arg != ArgEnd; ++Arg) {
-    TemplateArgument NewArg = getDerived().TransformTemplateArgument(*Arg);
-    if (NewArg.isNull())
+  llvm::SmallVector<TemplateArgumentLoc, 4> NewTemplateArgs(T->getNumArgs());
+  for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i)
+    if (getDerived().TransformTemplateArgument(TL.getArgLoc(i),
+                                               NewTemplateArgs[i]))
       return QualType();
 
-    NewTemplateArgs.push_back(NewArg);
+  // FIXME: maybe don't rebuild if all the template arguments are the same.
+
+  QualType Result =
+    getDerived().RebuildTemplateSpecializationType(Template,
+                                                   TL.getTemplateNameLoc(),
+                                                   TL.getLAngleLoc(),
+                                                   NewTemplateArgs.data(),
+                                                   NewTemplateArgs.size(),
+                                                   TL.getRAngleLoc());
+
+  if (!Result.isNull()) {
+    TemplateSpecializationTypeLoc NewTL
+      = TLB.push<TemplateSpecializationTypeLoc>(Result);
+    NewTL.setTemplateNameLoc(TL.getTemplateNameLoc());
+    NewTL.setLAngleLoc(TL.getLAngleLoc());
+    NewTL.setRAngleLoc(TL.getRAngleLoc());
+    for (unsigned i = 0, e = NewTemplateArgs.size(); i != e; ++i)
+      NewTL.setArgLocInfo(i, NewTemplateArgs[i].getLocInfo());
   }
 
-  // FIXME: early abort if all of the template arguments and such are the
-  // same.
-
-  // FIXME: We're missing the locations of the template name, '<', and '>'.
-  return getDerived().RebuildTemplateSpecializationType(Template,
-                                                        NewTemplateArgs.data(),
-                                                        NewTemplateArgs.size());
+  return Result;
 }
 
 template<typename Derived>
@@ -2754,9 +2853,12 @@
 QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB,
                                                        TypenameTypeLoc TL) {
   TypenameType *T = TL.getTypePtr();
+
+  /* FIXME: preserve source information better than this */
+  SourceRange SR(TL.getNameLoc());
+
   NestedNameSpecifier *NNS
-    = getDerived().TransformNestedNameSpecifier(T->getQualifier(),
-                        SourceRange(/*FIXME:*/getDerived().getBaseLocation()));
+    = getDerived().TransformNestedNameSpecifier(T->getQualifier(), SR);
   if (!NNS)
     return QualType();
 
@@ -2775,7 +2877,7 @@
 
     Result = getDerived().RebuildTypenameType(NNS, NewTemplateId);
   } else {
-    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier());
+    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier(), SR);
   }
   if (Result.isNull())
     return QualType();
@@ -3287,14 +3389,11 @@
 
   // FIXME: We're losing the explicit template arguments in this transformation.
 
-  llvm::SmallVector<TemplateArgument, 4> TransArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
   for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
-    TemplateArgument TransArg
-      = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
-    if (TransArg.isNull())
+    if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+                                               TransArgs[I]))
       return SemaRef.ExprError();
-    
-    TransArgs.push_back(TransArg);
   }
   
   // FIXME: Pass the qualifier/qualifier range along.
@@ -4367,14 +4466,11 @@
       return SemaRef.ExprError();
   }
   
-  llvm::SmallVector<TemplateArgument, 4> TransArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
   for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
-    TemplateArgument TransArg
-      = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
-    if (TransArg.isNull())
+    if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+                                               TransArgs[I]))
       return SemaRef.ExprError();
-
-    TransArgs.push_back(TransArg);
   }
 
   // FIXME: Would like to avoid rebuilding if nothing changed, but we can't
@@ -4627,14 +4723,11 @@
   if (Template.isNull())
     return SemaRef.ExprError();
 
-  llvm::SmallVector<TemplateArgument, 4> TransArgs;
+  llvm::SmallVector<TemplateArgumentLoc, 4> TransArgs(E->getNumTemplateArgs());
   for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {
-    TemplateArgument TransArg
-    = getDerived().TransformTemplateArgument(E->getTemplateArgs()[I]);
-    if (TransArg.isNull())
+    if (getDerived().TransformTemplateArgument(E->getTemplateArgs()[I],
+                                               TransArgs[I]))
       return SemaRef.ExprError();
-
-    TransArgs.push_back(TransArg);
   }
 
   return getDerived().RebuildCXXUnresolvedMemberExpr(move(Base),
@@ -4980,13 +5073,14 @@
 
 template<typename Derived>
 QualType TreeTransform<Derived>::RebuildTemplateSpecializationType(
-                                                        TemplateName Template,
-                                                 const TemplateArgument *Args,
-                                                           unsigned NumArgs) {
-  // FIXME: Missing source locations for the template name, <, >.
-  return SemaRef.CheckTemplateIdType(Template, getDerived().getBaseLocation(),
-                                     SourceLocation(), Args, NumArgs,
-                                     SourceLocation());
+                                                      TemplateName Template,
+                                             SourceLocation TemplateNameLoc,
+                                                   SourceLocation LAngleLoc,
+                                            const TemplateArgumentLoc *Args,
+                                                           unsigned NumArgs,
+                                                   SourceLocation RAngleLoc) {
+  return SemaRef.CheckTemplateIdType(Template, TemplateNameLoc, LAngleLoc,
+                                     Args, NumArgs, RAngleLoc);
 }
 
 template<typename Derived>