[cfe-commits] r86777 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Frontend/ lib/Parse/ lib/Sema/ test/SemaTemplate/

Douglas Gregor dgregor at apple.com
Tue Nov 10 17:00:40 PST 2009


Author: dgregor
Date: Tue Nov 10 19:00:40 2009
New Revision: 86777

URL: http://llvm.org/viewvc/llvm-project?rev=86777&view=rev
Log:
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. 


Modified:
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/TemplateBase.h
    cfe/trunk/include/clang/AST/TypeLoc.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/AST/TemplateBase.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/AST/TypePrinter.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
    cfe/trunk/test/SemaTemplate/temp_arg_template.cpp

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Nov 10 19:00:40 2009
@@ -699,13 +699,13 @@
   : public TemplateDecl, protected TemplateParmPosition {
 
   /// \brief The default template argument, if any.
-  Expr *DefaultArgument;
+  TemplateArgumentLoc DefaultArgument;
 
   TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
                            unsigned D, unsigned P,
                            IdentifierInfo *Id, TemplateParameterList *Params)
     : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
-      TemplateParmPosition(D, P), DefaultArgument(0)
+      TemplateParmPosition(D, P), DefaultArgument()
     { }
 
 public:
@@ -720,16 +720,17 @@
 
   /// \brief Determine whether this template parameter has a default
   /// argument.
-  bool hasDefaultArgument() const { return DefaultArgument; }
+  bool hasDefaultArgument() const { 
+    return !DefaultArgument.getArgument().isNull(); 
+  }
 
   /// \brief Retrieve the default argument, if any.
-  Expr *getDefaultArgument() const { return DefaultArgument; }
-
-  /// \brief Retrieve the location of the default argument, if any.
-  SourceLocation getDefaultArgumentLoc() const;
+  const TemplateArgumentLoc &getDefaultArgument() const { 
+    return DefaultArgument; 
+  }
 
   /// \brief Set the default argument for this template parameter.
-  void setDefaultArgument(Expr *DefArg) {
+  void setDefaultArgument(const TemplateArgumentLoc &DefArg) {
     DefaultArgument = DefArg;
   }
 

Modified: cfe/trunk/include/clang/AST/TemplateBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TemplateBase.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TemplateBase.h (original)
+++ cfe/trunk/include/clang/AST/TemplateBase.h Tue Nov 10 19:00:40 2009
@@ -18,6 +18,7 @@
 #include "llvm/ADT/APSInt.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TemplateName.h"
 
 namespace llvm {
   class FoldingSetNodeID;
@@ -48,21 +49,27 @@
 public:
   /// \brief The type of template argument we're storing.
   enum ArgKind {
+    /// \brief Represents an empty template argument, e.g., one that has not
+    /// been deduced.
     Null = 0,
     /// The template argument is a type. Its value is stored in the
     /// TypeOrValue field.
-    Type = 1,
-    /// The template argument is a declaration
-    Declaration = 2,
-    /// The template argument is an integral value stored in an llvm::APSInt.
-    Integral = 3,
+    Type,
+    /// The template argument is a declaration that was provided for a pointer
+    /// or reference non-type template parameter.
+    Declaration,
+    /// The template argument is an integral value stored in an llvm::APSInt
+    /// that was provided for an integral non-type template parameter. 
+    Integral,
+    /// The template argument is a template name that was provided for a 
+    /// template template parameter.
+    Template,
     /// The template argument is a value- or type-dependent expression
     /// stored in an Expr*.
-    Expression = 4,
-
+    Expression,
     /// The template argument is actually a parameter pack. Arguments are stored
     /// in the Args struct.
-    Pack = 5
+    Pack
   } Kind;
 
   /// \brief Construct an empty, invalid template argument.
@@ -82,12 +89,21 @@
   }
 
   /// \brief Construct an integral constant template argument.
-  TemplateArgument(const llvm::APSInt &Value, QualType Type)
-  : Kind(Integral) {
+  TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) {
     new (Integer.Value) llvm::APSInt(Value);
     Integer.Type = Type.getAsOpaquePtr();
   }
 
+  /// \brief Construct a template argument that is a template.
+  ///
+  /// This form of template argument is generally used for template template
+  /// parameters. However, the template name could be a dependent template
+  /// name that ends up being instantiated to a function template whose address
+  /// is taken.
+  TemplateArgument(TemplateName Name) : Kind(Template) {
+    TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer());
+  }
+  
   /// \brief Construct a template argument that is an expression.
   ///
   /// This form of template argument only occurs in template argument
@@ -172,6 +188,15 @@
     return reinterpret_cast<Decl *>(TypeOrValue);
   }
 
+  /// \brief Retrieve the template argument as a template name.
+  TemplateName getAsTemplate() const {
+    if (Kind != Template)
+      return TemplateName();
+    
+    return TemplateName::getFromVoidPointer(
+                                        reinterpret_cast<void *> (TypeOrValue));
+  }
+  
   /// \brief Retrieve the template argument as an integral value.
   llvm::APSInt *getAsIntegral() {
     if (Kind != Integral)
@@ -242,13 +267,18 @@
   union {
     Expr *Expression;
     DeclaratorInfo *Declarator;
+    struct {
+      unsigned QualifierRange[2];
+      unsigned TemplateNameLoc;
+    } Template;
   };
 
 #ifndef NDEBUG
   enum Kind {
     K_None,
     K_DeclaratorInfo,
-    K_Expression
+    K_Expression,
+    K_Template
   } Kind;
 #endif
 
@@ -273,6 +303,17 @@
       , Kind(K_Expression) 
 #endif
     {}
+  
+  TemplateArgumentLocInfo(SourceRange QualifierRange, 
+                          SourceLocation TemplateNameLoc)
+#ifndef NDEBUG
+    : Kind(K_Template)
+#endif
+  {
+    Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding();
+    Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding();
+    Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding();
+  }
 
   DeclaratorInfo *getAsDeclaratorInfo() const {
     assert(Kind == K_DeclaratorInfo);
@@ -284,6 +325,18 @@
     return Expression;
   }
 
+  SourceRange getTemplateQualifierRange() const {
+    assert(Kind == K_Template);
+    return SourceRange(
+                SourceLocation::getFromRawEncoding(Template.QualifierRange[0]),
+                SourceLocation::getFromRawEncoding(Template.QualifierRange[1]));
+  }
+  
+  SourceLocation getTemplateNameLoc() const {
+    assert(Kind == K_Template);
+    return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc);
+  }
+  
 #ifndef NDEBUG
   void validateForArgument(const TemplateArgument &Arg) {
     switch (Arg.getKind()) {
@@ -294,6 +347,9 @@
     case TemplateArgument::Declaration:
       assert(Kind == K_Expression);
       break;
+    case TemplateArgument::Template:
+      assert(Kind == K_Template);
+      break;
     case TemplateArgument::Integral:
     case TemplateArgument::Pack:
       assert(Kind == K_None);
@@ -329,8 +385,18 @@
     assert(Argument.getKind() == TemplateArgument::Expression);
   }
 
-  /// \brief - Fetches the start location of the argument.
+  TemplateArgumentLoc(const TemplateArgument &Argument, 
+                      SourceRange QualifierRange,
+                      SourceLocation TemplateNameLoc)
+    : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) {
+    assert(Argument.getKind() == TemplateArgument::Template);
+  }
+  
+  /// \brief - Fetches the primary location of the argument.
   SourceLocation getLocation() const {
+    if (Argument.getKind() == TemplateArgument::Template)
+      return getTemplateNameLoc();
+    
     return getSourceRange().getBegin();
   }
 
@@ -359,6 +425,16 @@
     assert(Argument.getKind() == TemplateArgument::Declaration);
     return LocInfo.getAsExpr();
   }
+  
+  SourceRange getTemplateQualifierRange() const {
+    assert(Argument.getKind() == TemplateArgument::Template);
+    return LocInfo.getTemplateQualifierRange();
+  }
+  
+  SourceLocation getTemplateNameLoc() const {
+    assert(Argument.getKind() == TemplateArgument::Template);
+    return LocInfo.getTemplateNameLoc();
+  }  
 };
 
 }

Modified: cfe/trunk/include/clang/AST/TypeLoc.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/TypeLoc.h (original)
+++ cfe/trunk/include/clang/AST/TypeLoc.h Tue Nov 10 19:00:40 2009
@@ -919,6 +919,10 @@
         Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0);
         break;
 
+      case TemplateArgument::Template:
+        Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation());
+        break;
+          
       case TemplateArgument::Integral:
       case TemplateArgument::Pack:
       case TemplateArgument::Null:

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Nov 10 19:00:40 2009
@@ -289,6 +289,10 @@
 def err_variadic_templates : Error<
   "variadic templates are only allowed in C++0x">;
   
+def err_default_template_template_parameter_not_template : Error<
+  "default template argument for a template template parameter must be a class "
+  "template">;
+  
 // C++ declarations
 def err_friend_decl_defines_class : Error<
   "cannot define a type in a friend declaration">;

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Tue Nov 10 19:00:40 2009
@@ -1577,7 +1577,7 @@
   /// parameter.
   virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam,
                                                      SourceLocation EqualLoc,
-                                                     ExprArg Default) {
+                                        const ParsedTemplateArgument &Default) {
   }
 
   /// ActOnTemplateParameterList - Called when a complete template

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Tue Nov 10 19:00:40 2009
@@ -1371,6 +1371,7 @@
                                bool AllowTypeAnnotation = true);
   void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0);
   bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs);
+  ParsedTemplateArgument ParseTemplateTemplateArgument();
   ParsedTemplateArgument ParseTemplateArgument();
   DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc,
                                        SourceLocation TemplateLoc,

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 10 19:00:40 2009
@@ -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()));

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -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
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Tue Nov 10 19:00:40 2009
@@ -695,6 +695,10 @@
     VisitType(Arg.getAsType());
     break;
 
+  case TemplateArgument::Template:
+    VisitTemplateName(Arg.getAsTemplate());
+    break;
+      
   case TemplateArgument::Declaration:
     VisitDecl(Arg.getAsDecl());
     break;

Modified: cfe/trunk/lib/AST/TemplateBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TemplateBase.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TemplateBase.cpp (original)
+++ cfe/trunk/lib/AST/TemplateBase.cpp Tue Nov 10 19:00:40 2009
@@ -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:

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Tue Nov 10 19:00:40 2009
@@ -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

Modified: cfe/trunk/lib/AST/TypePrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypePrinter.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/AST/TypePrinter.cpp (original)
+++ cfe/trunk/lib/AST/TypePrinter.cpp Tue Nov 10 19:00:40 2009
@@ -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;

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Tue Nov 10 19:00:40 2009
@@ -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:

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Tue Nov 10 19:00:40 2009
@@ -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:

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -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,33 +813,16 @@
          Tok.is(tok::greatergreater);
 }
 
-/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
-///
-///       template-argument: [C++ 14.2]
-///         constant-expression
-///         type-id
-///         id-expression
-ParsedTemplateArgument Parser::ParseTemplateArgument() {
-  // C++ [temp.arg]p2:
-  //   In a template-argument, an ambiguity between a type-id and an
-  //   expression is resolved to a type-id, regardless of the form of
-  //   the corresponding template-parameter.
-  //
-  // Therefore, we initially try to parse a type-id.  
-  if (isCXXTypeId(TypeIdAsTemplateArgument)) {
-    SourceLocation Loc = Tok.getLocation();
-    TypeResult TypeArg = ParseTypeName();
-    if (TypeArg.isInvalid())
-      return ParsedTemplateArgument();
-    
-    return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), 
-                                  Loc);
-  }
+/// \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:
@@ -843,63 +831,92 @@
   //
   // 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;
+  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)) {
-        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. 
+        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]
+///         constant-expression
+///         type-id
+///         id-expression
+ParsedTemplateArgument Parser::ParseTemplateArgument() {
+  // C++ [temp.arg]p2:
+  //   In a template-argument, an ambiguity between a type-id and an
+  //   expression is resolved to a type-id, regardless of the form of
+  //   the corresponding template-parameter.
+  //
+  // Therefore, we initially try to parse a type-id.  
+  if (isCXXTypeId(TypeIdAsTemplateArgument)) {
+    SourceLocation Loc = Tok.getLocation();
+    TypeResult TypeArg = ParseTypeName();
+    if (TypeArg.isInvalid())
+      return ParsedTemplateArgument();
     
-    // We don't have a template template argument; revert everything we have
-    // tentatively parsed.
-    TPA.Revert();
+    return ParsedTemplateArgument(ParsedTemplateArgument::Type, TypeArg.get(), 
+                                  Loc);
   }
   
+  // 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();
   OwningExprResult ExprArg = ParseConstantExpression();

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Nov 10 19:00:40 2009
@@ -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);
 

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Nov 10 19:00:40 2009
@@ -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

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 10 19:00:40 2009
@@ -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;

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Nov 10 19:00:40 2009
@@ -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:

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Tue Nov 10 19:00:40 2009
@@ -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);

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Tue Nov 10 19:00:40 2009
@@ -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(),

Modified: cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_nontype.cpp Tue Nov 10 19:00:40 2009
@@ -10,8 +10,7 @@
 A<1 >> 2> *a3; // expected-warning{{use of right-shift operator ('>>') in template argument will require parentheses in C++0x}}
 
 // C++ [temp.arg.nontype]p5:
-A<A> *a4; // expected-error{{must have an integral or enumeration type}} \
-          // FIXME: the error message above is a bit lame
+A<A> *a4; // expected-error{{must be an expression}}
 
 enum E { Enumerator = 17 };
 A<E> *a5; // expected-error{{template argument for non-type template parameter must be an expression}}

Modified: cfe/trunk/test/SemaTemplate/temp_arg_template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/temp_arg_template.cpp?rev=86777&r1=86776&r2=86777&view=diff

==============================================================================
--- cfe/trunk/test/SemaTemplate/temp_arg_template.cpp (original)
+++ cfe/trunk/test/SemaTemplate/temp_arg_template.cpp Tue Nov 10 19:00:40 2009
@@ -26,12 +26,9 @@
 C<Y> *a7;
 C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
 
-template<typename T> void f(int); // expected-note{{function template}}
+template<typename T> void f(int);
 
-// FIXME: we're right to provide an error message, but it should say
-// that we need a class template. We won't get this right until name
-// lookup of 'f' returns a TemplateDecl.
-A<f> *a9; // expected-error{{template argument does not refer to}}
+A<f> *a9; // expected-error{{must be a class template}}
 
 // FIXME: The code below is ill-formed, because of the evil digraph '<:'. 
 // We should provide a much better error message than we currently do.





More information about the cfe-commits mailing list