Introduce a new representation for template template
parameters. Rather than storing them as either declarations (for the
non-dependent case) or expressions (for the dependent case), we now
(always) store them as TemplateNames. 

The primary change here is to add a new kind of TemplateArgument,
which stores a TemplateName. However, making that change ripples to
every switch on a TemplateArgument's kind, also affecting
TemplateArgumentLocInfo/TemplateArgumentLoc, default template
arguments for template template parameters, type-checking of template
template arguments, etc.

This change is light on testing. It should fix several pre-existing
problems with template template parameters, such as:
  - the inability to use dependent template names as template template
  arguments
  - template template parameter default arguments cannot be
  instantiation

However, there are enough pieces missing that more implementation is
required before we can adequately test template template parameters. 



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86777 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index bb3559b..b5d9cac 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2357,12 +2357,14 @@
       return Arg;
 
     case TemplateArgument::Expression:
-      // FIXME: Build canonical expression?
       return Arg;
 
     case TemplateArgument::Declaration:
       return TemplateArgument(Arg.getAsDecl()->getCanonicalDecl());
 
+    case TemplateArgument::Template:
+      return TemplateArgument(getCanonicalTemplateName(Arg.getAsTemplate()));
+      
     case TemplateArgument::Integral:
       return TemplateArgument(*Arg.getAsIntegral(),
                               getCanonicalType(Arg.getIntegralType()));
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 9ebc91a..0c14714 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -220,7 +220,7 @@
       TemplateArgs.push_back(TemplateArgument(E));
     } else {
       TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*Param);
-      TemplateArgs.push_back(TemplateArgument(TTP));
+      TemplateArgs.push_back(TemplateArgument(TemplateName(TTP)));
     }
   }
 
@@ -285,11 +285,6 @@
   return new (C) TemplateTemplateParmDecl(DC, L, D, P, Id, Params);
 }
 
-SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
-  return DefaultArgument? DefaultArgument->getSourceRange().getBegin()
-                        : SourceLocation();
-}
-
 //===----------------------------------------------------------------------===//
 // TemplateArgumentListBuilder Implementation
 //===----------------------------------------------------------------------===//
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 02e0c74..4458c2b 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -695,6 +695,10 @@
     VisitType(Arg.getAsType());
     break;
 
+  case TemplateArgument::Template:
+    VisitTemplateName(Arg.getAsTemplate());
+    break;
+      
   case TemplateArgument::Declaration:
     VisitDecl(Arg.getAsDecl());
     break;
diff --git a/lib/AST/TemplateBase.cpp b/lib/AST/TemplateBase.cpp
index 94e1ca1..18a574c 100644
--- a/lib/AST/TemplateBase.cpp
+++ b/lib/AST/TemplateBase.cpp
@@ -58,6 +58,10 @@
     ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
     break;
 
+  case Template:
+    ID.AddPointer(getAsTemplate().getAsVoidPointer());
+    break;
+      
   case Integral:
     getAsIntegral()->Profile(ID);
     getIntegralType().Profile(ID);
@@ -82,10 +86,19 @@
   switch (Argument.getKind()) {
   case TemplateArgument::Expression:
     return getSourceExpression()->getSourceRange();
+      
   case TemplateArgument::Declaration:
     return getSourceDeclExpression()->getSourceRange();
+      
   case TemplateArgument::Type:
     return getSourceDeclaratorInfo()->getTypeLoc().getFullSourceRange();
+      
+  case TemplateArgument::Template:
+    if (getTemplateQualifierRange().isValid())
+      return SourceRange(getTemplateQualifierRange().getBegin(),
+                         getTemplateNameLoc());
+    return SourceRange(getTemplateNameLoc());
+      
   case TemplateArgument::Integral:
   case TemplateArgument::Pack:
   case TemplateArgument::Null:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 844589f..5ecc33c 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -807,6 +807,9 @@
   case TemplateArgument::Type:
     return Arg.getAsType()->isDependentType();
 
+  case TemplateArgument::Template:
+    return Arg.getAsTemplate().isDependent();
+      
   case TemplateArgument::Declaration:
   case TemplateArgument::Integral:
     // Never dependent
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index 807f7d8..ed12006 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -576,6 +576,11 @@
       Buffer = cast<NamedDecl>(Arg.getAsDecl())->getNameAsString();
       break;
       
+    case TemplateArgument::Template: {
+      llvm::raw_string_ostream s(Buffer);
+      Arg.getAsTemplate().print(s, Policy);
+    }
+      
     case TemplateArgument::Integral:
       Buffer = Arg.getAsIntegral()->toString(10, true);
       break;
diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp
index 5cee988..394d358 100644
--- a/lib/Frontend/PCHReader.cpp
+++ b/lib/Frontend/PCHReader.cpp
@@ -2185,6 +2185,14 @@
     return ReadDeclExpr();
   case TemplateArgument::Type:
     return GetDeclaratorInfo(Record, Index);
+  case TemplateArgument::Template: {
+    SourceLocation 
+      QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
+      QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
+      TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
+    return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
+                                   TemplateNameLoc);
+  }
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp
index 82922a9..2dcb8b0 100644
--- a/lib/Frontend/PCHWriter.cpp
+++ b/lib/Frontend/PCHWriter.cpp
@@ -2122,6 +2122,12 @@
   case TemplateArgument::Type:
     AddDeclaratorInfo(Arg.getLocInfo().getAsDeclaratorInfo(), Record);
     break;
+  case TemplateArgument::Template:
+    Record.push_back(
+                   Arg.getTemplateQualifierRange().getBegin().getRawEncoding());
+    Record.push_back(Arg.getTemplateQualifierRange().getEnd().getRawEncoding());
+    Record.push_back(Arg.getTemplateNameLoc().getRawEncoding());
+    break;
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
   case TemplateArgument::Declaration:
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index cf7d511..b5063ee 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -485,12 +485,17 @@
   // Get the a default value, if given.
   if (Tok.is(tok::equal)) {
     SourceLocation EqualLoc = ConsumeToken();
-    OwningExprResult DefaultExpr = ParseCXXIdExpression();
-    if (DefaultExpr.isInvalid())
+    ParsedTemplateArgument Default = ParseTemplateTemplateArgument();
+    if (Default.isInvalid()) {
+      Diag(Tok.getLocation(), 
+           diag::err_default_template_template_parameter_not_template);
+      static tok::TokenKind EndToks[] = { 
+        tok::comma, tok::greater, tok::greatergreater
+      };
+      SkipUntil(EndToks, 3, true, true);
       return Param;
-    else if (Param)
-      Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc,
-                                                    move(DefaultExpr));
+    } else if (Param)
+      Actions.ActOnTemplateTemplateParameterDefault(Param, EqualLoc, Default);
   }
 
   return Param;
@@ -808,6 +813,81 @@
          Tok.is(tok::greatergreater);
 }
 
+/// \brief Parse a C++ template template argument.
+ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
+  if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) &&
+      !Tok.is(tok::annot_cxxscope))
+    return ParsedTemplateArgument();
+
+  // C++0x [temp.arg.template]p1:
+  //   A template-argument for a template template-parameter shall be the name
+  //   of a class template or a template alias, expressed as id-expression.
+  //   
+  // We perform some tentative parsing at this point, to determine whether
+  // we have an id-expression that refers to a class template or template
+  // alias. The grammar we tentatively parse is:
+  //
+  //   nested-name-specifier[opt] template[opt] identifier
+  //
+  // followed by a token that terminates a template argument, such as ',', 
+  // '>', or (in some cases) '>>'.
+  TentativeParsingAction TPA(*this);
+  CXXScopeSpec SS; // nested-name-specifier, if present
+  ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, 
+                                 /*EnteringContext=*/false);
+  
+  if (SS.isSet() && Tok.is(tok::kw_template)) {
+    // Parse the optional 'template' keyword following the 
+    // nested-name-specifier.
+    SourceLocation TemplateLoc = ConsumeToken();
+    
+    if (Tok.is(tok::identifier)) {
+      // We appear to have a dependent template name.
+      UnqualifiedId Name;
+      Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+      ConsumeToken(); // the identifier
+      
+      // If the next token signals the end of a template argument,
+      // then we have a dependent template name that could be a template
+      // template argument.
+      if (isEndOfTemplateArgument(Tok)) {
+        TemplateTy Template
+        = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, 
+                                             /*ObjectType=*/0);
+        if (Template.get()) {
+          TPA.Commit();
+          return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+        }
+      }
+    } 
+  } else if (Tok.is(tok::identifier)) {
+    // We may have a (non-dependent) template name.
+    TemplateTy Template;
+    UnqualifiedId Name;
+    Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
+    ConsumeToken(); // the identifier
+    
+    if (isEndOfTemplateArgument(Tok)) {
+      TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, 
+                                                    /*ObjectType=*/0, 
+                                                    /*EnteringContext=*/false, 
+                                                    Template);
+      if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
+        // We have an id-expression that refers to a class template or
+        // (C++0x) template alias. 
+        TPA.Commit();
+        return ParsedTemplateArgument(SS, Template, Name.StartLocation);
+      }
+    }
+  }
+  
+  // We don't have a template template argument; revert everything we have
+  // tentatively parsed.
+  TPA.Revert();
+  
+  return ParsedTemplateArgument();
+}
+
 /// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
 ///
 ///       template-argument: [C++ 14.2]
@@ -830,75 +910,12 @@
     return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), 
                                   Loc);
   }
-
-  // C++0x [temp.arg.template]p1:
-  //   A template-argument for a template template-parameter shall be the name
-  //   of a class template or a template alias, expressed as id-expression.
-  // 
-  // We perform some tentative parsing at this point, to determine whether
-  // we have an id-expression that refers to a class template or template
-  // alias. The grammar we tentatively parse is:
-  //
-  //   nested-name-specifier[opt] template[opt] identifier
-  //
-  // followed by a token that terminates a template argument, such as ',', 
-  // '>', or (in some cases) '>>'.
-  if (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
-      Tok.is(tok::annot_cxxscope)) {
-    TentativeParsingAction TPA(*this);
-    CXXScopeSpec SS; // nested-name-specifier, if present
-    ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, 
-                                   /*EnteringContext=*/false);
-
-    if (SS.isSet() && Tok.is(tok::kw_template)) {
-      // Parse the optional 'template' keyword following the 
-      // nested-name-specifier.
-      SourceLocation TemplateLoc = ConsumeToken();
-      
-      if (Tok.is(tok::identifier)) {
-        // We appear to have a dependent template name.
-        UnqualifiedId Name;
-        Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-        ConsumeToken(); // the identifier
-        
-        // If the next token signals the end of a template argument,
-        // then we have a dependent template name that could be a template
-        // template argument.
-        if (isEndOfTemplateArgument(Tok)) {
-          TemplateTy Template
-            = Actions.ActOnDependentTemplateName(TemplateLoc, SS, Name, 
-                                                 /*ObjectType=*/0);
-          if (Template.get()) {
-            TPA.Commit();
-            return ParsedTemplateArgument(SS, Template, Name.StartLocation);
-          }
-        }
-      } 
-    } else if (Tok.is(tok::identifier)) {
-      // We may have a (non-dependent) template name.
-      TemplateTy Template;
-      UnqualifiedId Name;
-      Name.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
-      ConsumeToken(); // the identifier
-
-      if (isEndOfTemplateArgument(Tok)) {
-        TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, Name, 
-                                                      /*ObjectType=*/0, 
-                                                      /*EnteringContext=*/false, 
-                                                      Template);
-        if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
-          // We have an id-expression that refers to a class template or
-          // (C++0x) template alias. 
-          TPA.Commit();
-          return ParsedTemplateArgument(SS, Template, Name.StartLocation);
-        }
-      }
-    }
-    
-    // We don't have a template template argument; revert everything we have
-    // tentatively parsed.
-    TPA.Revert();
-  }
+  
+  // Try to parse a template template argument.
+  ParsedTemplateArgument TemplateTemplateArgument
+    = ParseTemplateTemplateArgument();
+  if (!TemplateTemplateArgument.isInvalid())
+    return TemplateTemplateArgument;
   
   // Parse a non-type template argument. 
   SourceLocation Loc = Tok.getLocation();
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 90f5806..6c88995 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2446,7 +2446,7 @@
                                                    unsigned Position);
   virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
                                                      SourceLocation EqualLoc,
-                                                     ExprArg Default);
+                                        const ParsedTemplateArgument &Default);
 
   virtual TemplateParamsTy *
   ActOnTemplateParameterList(unsigned Depth,
@@ -2606,13 +2606,14 @@
   bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                              QualType InstantiatedParamType, Expr *&Arg,
                              TemplateArgument &Converted);
-  bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, DeclRefExpr *Arg);
+  bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, 
+                             const TemplateArgumentLoc &Arg);
   bool TemplateParameterListsAreEqual(TemplateParameterList *New,
                                       TemplateParameterList *Old,
                                       bool Complain,
                                       bool IsTemplateTemplateParm = false,
                                       SourceLocation TemplateArgLoc
-                                       = SourceLocation());
+                                        = SourceLocation());
 
   bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams);
 
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 13a66aa..4f26138 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -1219,12 +1219,13 @@
                                         AssociatedClasses);
       break;
 
-    case TemplateArgument::Declaration:
+    case TemplateArgument::Template: {
       // [...] the namespaces in which any template template arguments are
       // defined; and the classes in which any member templates used as
       // template template arguments are defined.
+      TemplateName Template = Arg.getAsTemplate();
       if (ClassTemplateDecl *ClassTemplate
-            = dyn_cast<ClassTemplateDecl>(Arg.getAsDecl())) {
+                 = dyn_cast<ClassTemplateDecl>(Template.getAsTemplateDecl())) {
         DeclContext *Ctx = ClassTemplate->getDeclContext();
         if (CXXRecordDecl *EnclosingClass = dyn_cast<CXXRecordDecl>(Ctx))
           AssociatedClasses.insert(EnclosingClass);
@@ -1234,7 +1235,9 @@
         CollectNamespace(AssociatedNamespaces, Ctx);
       }
       break;
-
+    }
+      
+    case TemplateArgument::Declaration:
     case TemplateArgument::Integral:
     case TemplateArgument::Expression:
       // [Note: non-type template arguments do not contribute to the set of
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 32a6d6c..ce2ffc1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -284,6 +284,46 @@
   return 0;
 }
 
+static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef,
+                                            const ParsedTemplateArgument &Arg) {
+  
+  switch (Arg.getKind()) {
+  case ParsedTemplateArgument::Type: {
+    DeclaratorInfo *DI;
+    QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI);
+    if (!DI) 
+      DI = SemaRef.Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
+    return TemplateArgumentLoc(TemplateArgument(T), DI);
+  }
+    
+  case ParsedTemplateArgument::NonType: {
+    Expr *E = static_cast<Expr *>(Arg.getAsExpr());
+    return TemplateArgumentLoc(TemplateArgument(E), E);
+  }
+    
+  case ParsedTemplateArgument::Template: {
+    TemplateName Template
+      = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
+    return TemplateArgumentLoc(TemplateArgument(Template),
+                               Arg.getScopeSpec().getRange(),
+                               Arg.getLocation());
+  }
+  }
+  
+  llvm::llvm_unreachable("Unhandled parsed template argument");
+  return TemplateArgumentLoc();
+}
+                                                     
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
+                     llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
+ TemplateArgs.reserve(TemplateArgsIn.size());
+ 
+ for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I)
+   TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I]));
+}
+                                                     
 /// ActOnTypeParameter - Called when a C++ template type parameter
 /// (e.g., "typename T") has been parsed. Typename specifies whether
 /// the keyword "typename" was used to declare the type parameter
@@ -518,34 +558,22 @@
 /// parameter.
 void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD,
                                                  SourceLocation EqualLoc,
-                                                 ExprArg DefaultE) {
+                                        const ParsedTemplateArgument &Default) {
   TemplateTemplateParmDecl *TemplateParm
     = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>());
-
-  // Since a template-template parameter's default argument is an
-  // id-expression, it must be a DeclRefExpr.
-  DeclRefExpr *Default
-    = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get()));
-
+  
   // C++ [temp.param]p14:
   //   A template-parameter shall not be used in its own default argument.
   // FIXME: Implement this check! Needs a recursive walk over the types.
 
   // Check the well-formedness of the template argument.
-  if (!isa<TemplateDecl>(Default->getDecl())) {
-    Diag(Default->getSourceRange().getBegin(),
-         diag::err_template_arg_must_be_template)
-      << Default->getSourceRange();
-    TemplateParm->setInvalidDecl();
-    return;
-  }
-  if (CheckTemplateArgument(TemplateParm, Default)) {
+  TemplateArgumentLoc DefaultArg = translateTemplateArgument(*this, Default);
+  if (CheckTemplateArgument(TemplateParm, DefaultArg)) {
     TemplateParm->setInvalidDecl();
     return;
   }
 
-  DefaultE.release();
-  TemplateParm->setDefaultArgument(Default);
+  TemplateParm->setDefaultArgument(DefaultArg);
 }
 
 /// ActOnTemplateParameterList - Builds a TemplateParameterList that
@@ -924,8 +952,8 @@
         = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0;
       if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() &&
           NewTemplateParm->hasDefaultArgument()) {
-        OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc();
-        NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc();
+        OldDefaultLoc = OldTemplateParm->getDefaultArgument().getLocation();
+        NewDefaultLoc = NewTemplateParm->getDefaultArgument().getLocation();
         SawDefaultArgument = true;
         RedundantDefaultArg = true;
         PreviousDefaultArgLoc = NewDefaultLoc;
@@ -937,10 +965,12 @@
         // that points to a previous template template parameter.
         NewTemplateParm->setDefaultArgument(
                                         OldTemplateParm->getDefaultArgument());
-        PreviousDefaultArgLoc = OldTemplateParm->getDefaultArgumentLoc();
+        PreviousDefaultArgLoc
+          = OldTemplateParm->getDefaultArgument().getLocation();
       } else if (NewTemplateParm->hasDefaultArgument()) {
         SawDefaultArgument = true;
-        PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc();
+        PreviousDefaultArgLoc
+          = NewTemplateParm->getDefaultArgument().getLocation();
       } else if (SawDefaultArgument)
         MissingDefaultArg = true;
     }
@@ -1119,50 +1149,6 @@
   return ParamLists[NumParamLists - 1];
 }
 
-/// \brief Translates template arguments as provided by the parser
-/// into template arguments used by semantic analysis.
-void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn,
-                     llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) {
-  TemplateArgs.reserve(TemplateArgsIn.size());
-
-  for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) {
-    const ParsedTemplateArgument &Arg = TemplateArgsIn[I];
-    switch (Arg.getKind()) {
-    case ParsedTemplateArgument::Type: {
-      DeclaratorInfo *DI;
-      QualType T = Sema::GetTypeFromParser(Arg.getAsType(), &DI);
-      if (!DI) DI = Context.getTrivialDeclaratorInfo(T, Arg.getLocation());
-      TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(T), DI));
-      break;
-    }
-        
-    case ParsedTemplateArgument::NonType: {
-      Expr *E = static_cast<Expr *>(Arg.getAsExpr());
-      TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
-      break;
-    }
-      
-    case ParsedTemplateArgument::Template: {
-      TemplateName Template
-        = TemplateName::getFromVoidPointer(Arg.getAsTemplate().get());
-      
-      // FIXME: This is an egregious hack. We turn a nicely-parsed template name
-      // into a DeclRefExpr, because that's how we previously parsed template
-      // template parameters. This will disappear as part of the upcoming
-      // implementation of template template parameters.
-      const CXXScopeSpec &SS = Arg.getScopeSpec();
-      Expr *E = DeclRefExpr::Create(Context, 
-                                    (NestedNameSpecifier *)SS.getScopeRep(),
-                                    SS.getRange(), 
-                                    Template.getAsTemplateDecl(),
-                                    Arg.getLocation(),
-                                    Context.DependentTy, false, false);
-      TemplateArgs.push_back(TemplateArgumentLoc(TemplateArgument(E), E));
-    }
-    }
-  }
-}
-
 QualType Sema::CheckTemplateIdType(TemplateName Name,
                                    SourceLocation TemplateLoc,
                                    SourceLocation LAngleLoc,
@@ -1538,7 +1524,7 @@
 /// \param RAngleLoc the location of the right angle bracket ('>') that
 /// terminates the template-id.
 ///
-/// \param Param the template template parameter whose default we are
+/// \param Param the non-type template parameter whose default we are
 /// substituting into.
 ///
 /// \param Converted the list of template arguments provided for template
@@ -1566,6 +1552,52 @@
   return SemaRef.SubstExpr(Param->getDefaultArgument(), AllTemplateArgs);
 }
 
+/// \brief Substitute template arguments into the default template argument for
+/// the given template template parameter.
+///
+/// \param SemaRef the semantic analysis object for which we are performing
+/// the substitution.
+///
+/// \param Template the template that we are synthesizing template arguments 
+/// for.
+///
+/// \param TemplateLoc the location of the template name that started the
+/// template-id we are checking.
+///
+/// \param RAngleLoc the location of the right angle bracket ('>') that
+/// terminates the template-id.
+///
+/// \param Param the template template parameter whose default we are
+/// substituting into.
+///
+/// \param Converted the list of template arguments provided for template
+/// parameters that precede \p Param in the template parameter list.
+///
+/// \returns the substituted template argument, or NULL if an error occurred.
+static TemplateName
+SubstDefaultTemplateArgument(Sema &SemaRef,
+                             TemplateDecl *Template,
+                             SourceLocation TemplateLoc,
+                             SourceLocation RAngleLoc,
+                             TemplateTemplateParmDecl *Param,
+                             TemplateArgumentListBuilder &Converted) {
+  TemplateArgumentList TemplateArgs(SemaRef.Context, Converted,
+                                    /*TakeArgs=*/false);
+  
+  MultiLevelTemplateArgumentList AllTemplateArgs
+    = SemaRef.getTemplateInstantiationArgs(Template, &TemplateArgs);
+  
+  Sema::InstantiatingTemplate Inst(SemaRef, TemplateLoc,
+                                   Template, Converted.getFlatArguments(),
+                                   Converted.flatSize(),
+                                   SourceRange(TemplateLoc, RAngleLoc));
+  
+  return SemaRef.SubstTemplateName(
+                      Param->getDefaultArgument().getArgument().getAsTemplate(),
+                              Param->getDefaultArgument().getTemplateNameLoc(), 
+                                   AllTemplateArgs);
+}
+
 /// \brief Check that the given template argument list is well-formed
 /// for specializing the given template.
 bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
@@ -1666,9 +1698,17 @@
         if (!TempParm->hasDefaultArgument())
           break;
 
-        // FIXME: Subst default argument
-        Arg = TemplateArgumentLoc(TemplateArgument(TempParm->getDefaultArgument()),
-                                  TempParm->getDefaultArgument());
+        TemplateName Name = SubstDefaultTemplateArgument(*this, Template,
+                                                         TemplateLoc, 
+                                                         RAngleLoc, 
+                                                         TempParm,
+                                                         Converted);
+        if (Name.isNull())
+          return true;
+        
+        Arg = TemplateArgumentLoc(TemplateArgument(Name), 
+                    TempParm->getDefaultArgument().getTemplateQualifierRange(),
+                    TempParm->getDefaultArgument().getTemplateNameLoc());
       }
     } else {
       // Retrieve the template argument produced by the user.
@@ -1743,6 +1783,41 @@
         Converted.Append(Arg.getArgument());
         break;
 
+      case TemplateArgument::Template:
+        // We were given a template template argument. It may not be ill-formed;
+        // see below.
+        if (DependentTemplateName *DTN
+             = Arg.getArgument().getAsTemplate().getAsDependentTemplateName()) {
+          // We have a template argument such as \c T::template X, which we
+          // parsed as a template template argument. However, since we now
+          // know that we need a non-type template argument, convert this
+          // template name into an expression.          
+          Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(),
+                                                        Context.DependentTy,
+                                                      Arg.getTemplateNameLoc(),
+                                                Arg.getTemplateQualifierRange(),
+                                                        DTN->getQualifier(),
+                                                  /*isAddressOfOperand=*/false);
+                                                        
+          TemplateArgument Result;
+          if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
+            Invalid = true;
+          else
+            Converted.Append(Result);
+          
+          break;
+        }
+          
+        // We have a template argument that actually does refer to a class
+        // template, template alias, or template template parameter, and
+        // therefore cannot be a non-type template argument.
+        Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr)
+          << Arg.getSourceRange();
+          
+        Diag((*Param)->getLocation(), diag::note_template_param_here);
+        Invalid = true;
+        break;
+          
       case TemplateArgument::Type: {
         // We have a non-type template parameter but the template
         // argument is a type.
@@ -1780,38 +1855,28 @@
         assert(false && "Should never see a NULL template argument here");
         break;
 
-      case TemplateArgument::Expression: {
-        Expr *ArgExpr = Arg.getArgument().getAsExpr();
-        if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
-            isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
-          if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
-            Invalid = true;
-
-          // Add the converted template argument.
-          Decl *D
-            = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl();
-          Converted.Append(TemplateArgument(D));
-          continue;
-        }
-      }
-        // fall through
-
-      case TemplateArgument::Type: {
+      case TemplateArgument::Template:
+        if (CheckTemplateArgument(TempParm, Arg))
+          Invalid = true;
+        else
+          Converted.Append(Arg.getArgument());
+        break;
+          
+      case TemplateArgument::Expression:
+      case TemplateArgument::Type:
         // We have a template template parameter but the template
         // argument does not refer to a template.
         Diag(Arg.getLocation(), diag::err_template_arg_must_be_template);
         Invalid = true;
         break;
-      }
 
       case TemplateArgument::Declaration:
-        // We've already checked this template argument, so just copy
-        // it to the list of converted arguments.
-        Converted.Append(Arg.getArgument());
+        llvm::llvm_unreachable(
+                       "Declaration argument with template template parameter");
         break;
-
       case TemplateArgument::Integral:
-        assert(false && "Integral argument with template template parameter");
+        llvm::llvm_unreachable(
+                          "Integral argument with template template parameter");
         break;
 
       case TemplateArgument::Pack:
@@ -2357,9 +2422,14 @@
 /// This routine implements the semantics of C++ [temp.arg.template].
 /// It returns true if an error occurred, and false otherwise.
 bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param,
-                                 DeclRefExpr *Arg) {
-  assert(isa<TemplateDecl>(Arg->getDecl()) && "Only template decls allowed");
-  TemplateDecl *Template = cast<TemplateDecl>(Arg->getDecl());
+                                 const TemplateArgumentLoc &Arg) {
+  TemplateName Name = Arg.getArgument().getAsTemplate();
+  TemplateDecl *Template = Name.getAsTemplateDecl();
+  if (!Template) {
+    // Any dependent template name is fine.
+    assert(Name.isDependent() && "Non-dependent template isn't a declaration?");
+    return false;
+  }
 
   // C++ [temp.arg.template]p1:
   //   A template-argument for a template template-parameter shall be
@@ -2376,7 +2446,7 @@
       !isa<TemplateTemplateParmDecl>(Template)) {
     assert(isa<FunctionTemplateDecl>(Template) &&
            "Only function templates are possible here");
-    Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template);
+    Diag(Arg.getLocation(), diag::err_template_arg_not_class_template);
     Diag(Template->getLocation(), diag::note_template_arg_refers_here_func)
       << Template;
   }
@@ -2384,7 +2454,7 @@
   return !TemplateParameterListsAreEqual(Template->getTemplateParameters(),
                                          Param->getTemplateParameters(),
                                          true, true,
-                                         Arg->getSourceRange().getBegin());
+                                         Arg.getLocation());
 }
 
 /// \brief Determine whether the given template parameter lists are
@@ -2735,16 +2805,9 @@
       } else if (TemplateTemplateParmDecl *TTP
                    = dyn_cast<TemplateTemplateParmDecl>(
                                                  TemplateParams->getParam(I))) {
-        // FIXME: We should settle on either Declaration storage or
-        // Expression storage for template template parameters.
+        TemplateName Name = ArgList[I].getAsTemplate();
         TemplateTemplateParmDecl *ArgDecl
-          = dyn_cast_or_null<TemplateTemplateParmDecl>(
-                                                  ArgList[I].getAsDecl());
-        if (!ArgDecl)
-          if (DeclRefExpr *DRE
-                = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr()))
-            ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl());
-
+          = dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
         if (!ArgDecl ||
             ArgDecl->getIndex() != TTP->getIndex() ||
             ArgDecl->getDepth() != TTP->getDepth())
@@ -2871,12 +2934,11 @@
         }
       } else {
         TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param);
-        if (Expr *DefArg = TTP->getDefaultArgument()) {
-          Diag(TTP->getDefaultArgumentLoc(),
+        if (TTP->hasDefaultArgument()) {
+          Diag(TTP->getDefaultArgument().getLocation(),
                diag::err_default_arg_in_partial_spec)
-            << DefArg->getSourceRange();
-          TTP->setDefaultArgument(0);
-          DefArg->Destroy(Context);
+            << TTP->getDefaultArgument().getSourceRange();
+          TTP->setDefaultArgument(TemplateArgumentLoc());
         }
       }
     }
@@ -4580,6 +4642,14 @@
         break;
       }
         
+      case TemplateArgument::Template: {
+        std::string Str;
+        llvm::raw_string_ostream OS(Str);
+        Args[I].getAsTemplate().print(OS, Context.PrintingPolicy);
+        Result += OS.str();
+        break;
+      }
+        
       case TemplateArgument::Integral: {
         Result += Args[I].getAsIntegral()->toString(10);
         break;
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 7b5ad7f..2eb3af2 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -785,13 +785,32 @@
     break;
 
   case TemplateArgument::Type:
-    assert(Arg.getKind() == TemplateArgument::Type && "Type/value mismatch");
-    return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
-                                   Arg.getAsType(), Info, Deduced, 0);
-
+    if (Arg.getKind() == TemplateArgument::Type)
+      return DeduceTemplateArguments(Context, TemplateParams, Param.getAsType(),
+                                     Arg.getAsType(), Info, Deduced, 0);
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+      
+  case TemplateArgument::Template:
+#if 0
+      // FIXME: We need template argument deduction for template template
+      // parameters.
+      if (Arg.getKind() == TemplateArgument::Template)
+      return DeduceTemplateArguments(Context, TemplateParams, 
+                                     Param.getAsTemplate(),
+                                     Arg.getAsTemplate(), Info, Deduced, 0);
+#endif
+    Info.FirstArg = Param;
+    Info.SecondArg = Arg;
+    return Sema::TDK_NonDeducedMismatch;
+      
   case TemplateArgument::Declaration:
-    // FIXME: Implement this check
-    assert(false && "Unimplemented template argument deduction case");
+    if (Arg.getKind() == TemplateArgument::Declaration &&
+        Param.getAsDecl()->getCanonicalDecl() ==
+          Arg.getAsDecl()->getCanonicalDecl())
+      return Sema::TDK_Success;
+      
     Info.FirstArg = Param;
     Info.SecondArg = Arg;
     return Sema::TDK_NonDeducedMismatch;
@@ -885,13 +904,21 @@
       return X.getAsDecl()->getCanonicalDecl() ==
              Y.getAsDecl()->getCanonicalDecl();
 
+    case TemplateArgument::Template:
+      return Context.getCanonicalTemplateName(X.getAsTemplate())
+               .getAsVoidPointer() ==
+             Context.getCanonicalTemplateName(Y.getAsTemplate())
+               .getAsVoidPointer();
+      
     case TemplateArgument::Integral:
       return *X.getAsIntegral() == *Y.getAsIntegral();
 
-    case TemplateArgument::Expression:
-      // FIXME: We assume that all expressions are distinct, but we should
-      // really check their canonical forms.
-      return false;
+    case TemplateArgument::Expression: {
+      llvm::FoldingSetNodeID XID, YID;
+      X.getAsExpr()->Profile(XID, Context, true);
+      Y.getAsExpr()->Profile(YID, Context, true);      
+      return XID == YID;
+    }
 
     case TemplateArgument::Pack:
       if (X.pack_size() != Y.pack_size())
@@ -1030,15 +1057,6 @@
           Info.FirstArg = Partial->getTemplateArgs()[I];
           return TDK_SubstitutionFailure;
         }
-      } else if (TemplateTemplateParmDecl *TTP
-                   = dyn_cast<TemplateTemplateParmDecl>(Param)) {
-        // FIXME: template template arguments should really resolve to decls
-        DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(InstExpr);
-        if (!DRE || CheckTemplateArgument(TTP, DRE)) {
-          Info.Param = makeTemplateParameter(Param);
-          Info.FirstArg = Partial->getTemplateArgs()[I];
-          return TDK_SubstitutionFailure;
-        }
       }
     }
 
@@ -2153,6 +2171,9 @@
     return;
   }
   
+  if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName())
+    MarkUsedTemplateParameters(SemaRef, QTN->getQualifier(), OnlyDeduced, 
+                               Depth, Used);
   if (DependentTemplateName *DTN = Name.getAsDependentTemplateName())
     MarkUsedTemplateParameters(SemaRef, DTN->getQualifier(), OnlyDeduced, 
                                Depth, Used);
@@ -2309,6 +2330,7 @@
   switch (TemplateArg.getKind()) {
   case TemplateArgument::Null:
   case TemplateArgument::Integral:
+    case TemplateArgument::Declaration:
     break;
 
   case TemplateArgument::Type:
@@ -2316,12 +2338,9 @@
                                Depth, Used);
     break;
 
-  case TemplateArgument::Declaration:
-    if (TemplateTemplateParmDecl *TTP
-          = dyn_cast<TemplateTemplateParmDecl>(TemplateArg.getAsDecl())) {
-      if (TTP->getDepth() == Depth)
-        Used[TTP->getIndex()] = true;
-    }
+  case TemplateArgument::Template:
+    MarkUsedTemplateParameters(SemaRef, TemplateArg.getAsTemplate(), 
+                               OnlyDeduced, Depth, Used);
     break;
 
   case TemplateArgument::Expression:
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 9e8dc2e..74f521e 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -452,10 +452,11 @@
 
   if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(D)) {
     if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
-      assert(TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsDecl() &&
+      TemplateName Template
+        = TemplateArgs(TTP->getDepth(), TTP->getPosition()).getAsTemplate();
+      assert(!Template.isNull() && Template.getAsTemplateDecl() &&
              "Wrong kind of template template argument");
-      return cast<TemplateDecl>(TemplateArgs(TTP->getDepth(),
-                                             TTP->getPosition()).getAsDecl());
+      return Template.getAsTemplateDecl();
     }
 
     // If the corresponding template argument is NULL or non-existent, it's
@@ -466,9 +467,8 @@
                                           TTP->getPosition()))
       return D;
 
-    // FIXME: Implement depth reduction of template template parameters
-    assert(false &&
-      "Reducing depth of template template parameters is not yet implemented");
+    // Fall through to find the instantiated declaration for this template
+    // template parameter.
   }
 
   return SemaRef.FindInstantiatedDecl(cast<NamedDecl>(D), TemplateArgs);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 799d01b..2095fba 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -1957,6 +1957,10 @@
                                             
     break;
 
+  case TemplateArgument::Template:
+    Output = TemplateArgumentLoc(Arg, SourceRange(), Loc);
+    break;
+      
   case TemplateArgument::Expression:
     Output = TemplateArgumentLoc(Arg, Arg.getAsExpr());
     break;
@@ -1997,7 +2001,7 @@
     DeclarationName Name;
     if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl()))
       Name = ND->getDeclName();
-    TemporaryBase Rebase(*this, SourceLocation(), Name);
+    TemporaryBase Rebase(*this, Input.getLocation(), Name);
     Decl *D = getDerived().TransformDecl(Arg.getAsDecl());
     if (!D) return true;
 
@@ -2018,6 +2022,19 @@
     return false;
   }
 
+  case TemplateArgument::Template: {
+    TemporaryBase Rebase(*this, Input.getLocation(), DeclarationName());    
+    TemplateName Template
+      = getDerived().TransformTemplateName(Arg.getAsTemplate());
+    if (Template.isNull())
+      return true;
+    
+    Output = TemplateArgumentLoc(TemplateArgument(Template),
+                                 Input.getTemplateQualifierRange(),
+                                 Input.getTemplateNameLoc());
+    return false;
+  }
+      
   case TemplateArgument::Expression: {
     // Template argument expressions are not potentially evaluated.
     EnterExpressionEvaluationContext Unevaluated(getSema(),