]> granicus.if.org Git - clang/commitdiff
Implement template instantiation for ClassTemplateSpecializationTypes,
authorDouglas Gregor <dgregor@apple.com>
Mon, 9 Mar 2009 23:48:35 +0000 (23:48 +0000)
committerDouglas Gregor <dgregor@apple.com>
Mon, 9 Mar 2009 23:48:35 +0000 (23:48 +0000)
such as replacing 'T' in vector<T>. There are a few aspects to this:

  - Extend TemplateArgument to allow arbitrary expressions (an
    Expr*), and switch ClassTemplateSpecializationType to store
    TemplateArguments rather than it's own type-or-expression
    representation.

  - ClassTemplateSpecializationType can now store dependent types. In
    that case, the canonical type is another
    ClassTemplateSpecializationType (with default template arguments
    expanded) rather than a declaration (we don't build Decls for
    dependent types).

  - Split ActOnClassTemplateId into ActOnClassTemplateId (called from
    the parser) and CheckClassTemplateId (called from
    ActOnClassTemplateId and InstantiateType). They're smart enough to
    handle dependent types, now.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66509 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/ASTContext.h
include/clang/AST/DeclTemplate.h
include/clang/AST/Type.h
lib/AST/ASTContext.cpp
lib/AST/DeclTemplate.cpp
lib/AST/Type.cpp
lib/AST/TypeSerialization.cpp
lib/Sema/Sema.h
lib/Sema/SemaDeclCXX.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaTemplate/temp_arg_type.cpp

index ca2b79579b453c26013c62f2e0519293330a4d2c..8a8be1e775d01537e0af8c719db661c862361960 100644 (file)
@@ -275,9 +275,9 @@ public:
                                    IdentifierInfo *Name = 0);
 
   QualType getClassTemplateSpecializationType(TemplateDecl *Template,
+                                              const TemplateArgument *Args,
                                               unsigned NumArgs,
-                                              uintptr_t *Args, bool *ArgIsType,
-                                              QualType Canon);
+                                              QualType Canon = QualType());
 
   /// getObjCQualifiedInterfaceType - Return a 
   /// ObjCQualifiedInterfaceType type for the given interface decl and
index d93bbf5562fa4c0c3059de607ee63690e2c86fe3..cc309b4ea5fe94f08c5c83293f312e2fa0d61b94 100644 (file)
@@ -68,6 +68,11 @@ public:
 
   unsigned size() const { return NumParams; }
 
+  const Decl* getParam(unsigned Idx) const {
+    assert(Idx < size() && "Template parameter index out-of-range");
+    return begin()[Idx];
+  }
+
   /// \btief Returns the minimum number of arguments needed to form a
   /// template specialization. This may be fewer than the number of
   /// template parameters, if some of the parameters have default
@@ -400,51 +405,72 @@ protected:
 /// specialization.
 class TemplateArgument {
   union {
-    uintptr_t TypeOrDeclaration;
+    uintptr_t TypeOrValue;
     char IntegralValue[sizeof(llvm::APInt)];
   };
 
+  /// \brief Location of the beginning of this template argument.
+  SourceLocation StartLoc;
+
 public:
   /// \brief The type of template argument we're storing.
   enum ArgKind {
     /// The template argument is a type. It's value is stored in the
-    /// TypeOrDeclaration field.
+    /// TypeOrValue field.
     Type = 0,
     /// The template argument is a declaration
     Declaration = 1,
     /// The template argument is an integral value stored in an llvm::APInt.
-    Integral = 2
+    Integral = 2,
+    /// The template argument is a value- or type-dependent expression
+    /// stored in an Expr*.
+    Expression = 3
   } Kind;
 
+  /// \brief Construct an empty, invalid template argument.
+  TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Type) { }
+
   /// \brief Construct a template type argument.
-  TemplateArgument(QualType T) : Kind(Type) {
-    assert(T->isCanonical() && 
-           "Template arguments always use the canonical type");
-    TypeOrDeclaration = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+  TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
+    TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+    StartLoc = Loc;
   }
 
   /// \brief Construct a template argument that refers to a
   /// declaration, which is either an external declaration or a
   /// template declaration.
-  TemplateArgument(Decl *D) : Kind(Declaration) {
+  TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
     // FIXME: Need to be sure we have the "canonical" declaration!
-    TypeOrDeclaration = reinterpret_cast<uintptr_t>(D);
+    TypeOrValue = reinterpret_cast<uintptr_t>(D);
+    StartLoc = Loc;
   }
 
   /// \brief Construct an integral constant template argument.
-  TemplateArgument(const llvm::APInt &Value) : Kind(Integral) {
+  TemplateArgument(SourceLocation Loc, const llvm::APInt &Value)
+    : Kind(Integral) {
     new (IntegralValue) llvm::APInt(Value);
+    StartLoc = Loc;
   }
 
+  /// \brief Construct a template argument that is an expression. 
+  ///
+  /// This form of template argument only occurs in template argument
+  /// lists used for dependent types and for expression; it will not
+  /// occur in a non-dependent, canonical template argument list.
+  TemplateArgument(Expr *E);
+
   /// \brief Copy constructor for a template argument.
   TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
     if (Kind == Integral)
       new (IntegralValue) llvm::APInt(*Other.getAsIntegral());
     else
-      TypeOrDeclaration = Other.TypeOrDeclaration;
+      TypeOrValue = Other.TypeOrValue;
+    StartLoc = Other.StartLoc;
   }
 
   TemplateArgument& operator=(const TemplateArgument& Other) {
+    // FIXME: Does not provide the strong guarantee for exception
+    // safety.
     using llvm::APInt;
 
     if (Kind == Other.Kind && Kind == Integral) {
@@ -460,8 +486,10 @@ public:
       if (Other.Kind == Integral)
         new (IntegralValue) llvm::APInt(*Other.getAsIntegral());
       else
-        TypeOrDeclaration = Other.TypeOrDeclaration;
+        TypeOrValue = Other.TypeOrValue;
     }
+    StartLoc = Other.StartLoc;
+
     return *this;
   }
 
@@ -481,14 +509,14 @@ public:
       return QualType();
 
     return QualType::getFromOpaquePtr(
-                                 reinterpret_cast<void*>(TypeOrDeclaration));
+                                 reinterpret_cast<void*>(TypeOrValue));
   }
 
   /// \brief Retrieve the template argument as a declaration.
   Decl *getAsDecl() const {
     if (Kind != Declaration)
       return 0;
-    return reinterpret_cast<Decl *>(TypeOrDeclaration);
+    return reinterpret_cast<Decl *>(TypeOrValue);
   }
 
   /// \brief Retrieve the template argument as an integral value.
@@ -502,6 +530,17 @@ public:
     return const_cast<TemplateArgument*>(this)->getAsIntegral();
   }
 
+  /// \brief Retrieve the template argument as an expression.
+  Expr *getAsExpr() const {
+    if (Kind != Expression)
+      return 0;
+
+    return reinterpret_cast<Expr *>(TypeOrValue);
+  }
+
+  /// \brief Retrieve the location where the template argument starts.
+  SourceLocation getLocation() const { return StartLoc; }
+
   /// \brief Used to insert TemplateArguments into FoldingSets.
   void Profile(llvm::FoldingSetNodeID &ID) const {
     ID.AddInteger(Kind);
@@ -517,6 +556,11 @@ public:
     case Integral:
       getAsIntegral()->Profile(ID);
       break;
+
+    case Expression:
+      // FIXME: We need a canonical representation of expressions.
+      ID.AddPointer(getAsExpr());
+      break;
     }
   }
 };
index b6a1ec17b9fca4476e7cccd46baabab83c448478..1c0a081c4504e02437f8d87ecff7a73861d35236 100644 (file)
@@ -46,6 +46,7 @@ namespace clang {
   class Stmt;
   class SourceLocation;
   class StmtIteratorBase;
+  class TemplateArgument;
 
   // Provide forward declarations for all of the *Type classes
 #define TYPE(Class, Base) class Class##Type;
@@ -1430,100 +1431,52 @@ class ClassTemplateSpecializationType
   // possibly with template-names preceded by a nested-name-specifier.
   TemplateDecl *Template;
 
+  /// \brief - The number of template arguments named in this class
+  /// template specialization.
   unsigned NumArgs;
 
-  ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
-                                  uintptr_t *Args, bool *ArgIsType,
-                                  QualType Canon);
+  ClassTemplateSpecializationType(TemplateDecl *T, 
+                                  const TemplateArgument *Args,
+                                  unsigned NumArgs, QualType Canon);
 
-  /// \brief Retrieve the number of packed words that precede the
-  /// actual arguments.
-  ///
-  /// The flags that specify whether each argument is a type or an
-  /// expression are packed into the
-  /// ClassTemplateSpecializationType. This routine computes the
-  /// number of pointer-sized words we need to store this information,
-  /// based on the number of template arguments
-  static unsigned getNumPackedWords(unsigned NumArgs) {
-    const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
-    return NumArgs / BitsPerWord + (NumArgs % BitsPerWord > 0);
-  }
-
-  /// \brief Pack the given boolean values into words.
-  static void 
-  packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words);
-  
   virtual void Destroy(ASTContext& C);
 
   friend class ASTContext;  // ASTContext creates these
 
 public:
+  /// \brief Determine whether any of the given template arguments are
+  /// dependent.
+  static bool anyDependentTemplateArguments(const TemplateArgument *Args,
+                                            unsigned NumArgs);  
+
+  typedef const TemplateArgument * iterator;
+
+  iterator begin() const { return getArgs(); }
+  iterator end() const;
+
   /// \brief Retrieve the template that we are specializing.
   TemplateDecl *getTemplate() const { return Template; }
 
-  /// \briefe Retrieve the number of template arguments.
+  /// \brief Retrieve the template arguments.
+  const TemplateArgument *getArgs() const { 
+    return reinterpret_cast<const TemplateArgument *>(this + 1);
+  }
+
+  /// \brief Retrieve the number of template arguments.
   unsigned getNumArgs() const { return NumArgs; }
 
   /// \brief Retrieve a specific template argument as a type.
   /// \precondition @c isArgType(Arg)
-  QualType getArgAsType(unsigned Arg) const {
-    assert(isArgType(Arg) && "Argument is not a type");
-    return QualType::getFromOpaquePtr(
-                          reinterpret_cast<void *>(getArgAsOpaqueValue(Arg)));
-  }
-
-  /// \brief Retrieve a specific template argument as an expression.
-  /// \precondition @c !isArgType(Arg)
-  Expr *getArgAsExpr(unsigned Arg) const {
-    assert(!isArgType(Arg) && "Argument is not an expression");
-    return reinterpret_cast<Expr *>(getArgAsOpaqueValue(Arg));
-  }
-
-  /// \brief Retrieve the specified template argument as an opaque value.
-  uintptr_t getArgAsOpaqueValue(unsigned Arg) const;
-
-  /// \brief Determine whether the given template argument is a type.
-  bool isArgType(unsigned Arg) const;
+  const TemplateArgument &getArg(unsigned Idx) const;
 
   virtual void getAsStringInternal(std::string &InnerString) const;
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    // Add the template
-    ID.AddPointer(Template);
-
-    // Add the packed words describing what kind of template arguments
-    // we have.
-    // FIXME: Would like to be smarter about the profile of expressions, 
-    // so that we can combine expression nodes more effectively.
-    uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
-    for (unsigned Packed = 0, NumPacked = getNumPackedWords(NumArgs); 
-         Packed != NumPacked; ++Packed)
-      ID.AddInteger(Data[Packed]);
-
-    // Add the template arguments themselves.
-    for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-      ID.AddInteger(getArgAsOpaqueValue(Arg));
+    Profile(ID, Template, getArgs(), NumArgs);
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, TemplateDecl *T,
-                      unsigned NumArgs, uintptr_t *Args, bool *ArgIsType) {
-    // Add the template
-    ID.AddPointer(T);
-
-    // Add the packed words describing what kind of template arguments
-    // we have.
-    unsigned NumPackedWords = getNumPackedWords(NumArgs);
-    unsigned NumPackedBytes = NumPackedWords * sizeof(uintptr_t);
-    uintptr_t *PackedWords 
-      = reinterpret_cast<uintptr_t *>(alloca(NumPackedBytes));
-    packBooleanValues(NumArgs, ArgIsType, PackedWords);
-    for (unsigned Packed = 0; Packed != NumPackedWords; ++Packed)
-      ID.AddInteger(PackedWords[Packed]);
-
-    // Add the template arguments themselves.
-    for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-      ID.AddInteger(Args[Arg]);
-  }
+                      const TemplateArgument *Args, unsigned NumArgs);
 
   static bool classof(const Type *T) { 
     return T->getTypeClass() == ClassTemplateSpecialization; 
index 4579fb5a6053172f982437d7a0d75d7bad0a09f0..a51f432880ec214c2d554e0f2ec601acbeddbcdd 100644 (file)
@@ -1309,14 +1309,15 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index,
 
 QualType 
 ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
+                                               const TemplateArgument *Args,
                                                unsigned NumArgs,
-                                               uintptr_t *Args, bool *ArgIsType,
                                                QualType Canon) {
-  Canon = getCanonicalType(Canon);
+  if (!Canon.isNull())
+    Canon = getCanonicalType(Canon);
 
   llvm::FoldingSetNodeID ID;
-  ClassTemplateSpecializationType::Profile(ID, Template, NumArgs, Args, 
-                                           ArgIsType);
+  ClassTemplateSpecializationType::Profile(ID, Template, Args, NumArgs);
+
   void *InsertPos = 0;
   ClassTemplateSpecializationType *Spec
     = ClassTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos);
@@ -1324,13 +1325,11 @@ ASTContext::getClassTemplateSpecializationType(TemplateDecl *Template,
   if (Spec)
     return QualType(Spec, 0);
   
-  void *Mem = Allocate(sizeof(ClassTemplateSpecializationType) + 
-                       (sizeof(uintptr_t) * 
-                        (ClassTemplateSpecializationType::
-                           getNumPackedWords(NumArgs) + 
-                         NumArgs)), 8);
-  Spec = new (Mem) ClassTemplateSpecializationType(Template, NumArgs, Args,
-                                                   ArgIsType, Canon);
+  void *Mem = Allocate((sizeof(ClassTemplateSpecializationType) + 
+                        sizeof(TemplateArgument) * NumArgs),
+                       8);
+  Spec = new (Mem) ClassTemplateSpecializationType(Template, Args, NumArgs, 
+                                                   Canon);
   Types.push_back(Spec);
   ClassTemplateSpecializationTypes.InsertNode(Spec, InsertPos);
 
index ed4fd44e707b7541bcf211d1cc5f649ad226af8b..ac76c258a71d61b9986e5ec779f146037edec425 100644 (file)
@@ -144,6 +144,15 @@ SourceLocation TemplateTemplateParmDecl::getDefaultArgumentLoc() const {
                         : SourceLocation(); 
 }
 
+//===----------------------------------------------------------------------===//
+// TemplateArgument Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
+  TypeOrValue = reinterpret_cast<uintptr_t>(E);
+  StartLoc = E->getSourceRange().getBegin();
+}
+
 //===----------------------------------------------------------------------===//
 // ClassTemplateSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
index 3b06b4ee28d26003aacc79a4059a03fe9367ba42..412b0cf8341c5e49c68eedd2fa01bac88fbe0428 100644 (file)
@@ -921,59 +921,77 @@ bool EnumType::classof(const TagType *TT) {
   return isa<EnumDecl>(TT->getDecl());
 }
 
-void 
+bool 
 ClassTemplateSpecializationType::
-packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) {
-  const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
-
-  for (unsigned PW = 0, NumPackedWords = getNumPackedWords(NumArgs), Arg = 0;
-       PW != NumPackedWords; ++PW) {
-    uintptr_t Word = 0;
-    for (unsigned Bit = 0; Bit < BitsPerWord && Arg < NumArgs; ++Bit, ++Arg) {
-      Word <<= 1;
-      Word |= Values[Arg];
+anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
+  for (unsigned Idx = 0; Idx < NumArgs; ++Idx) {
+    switch (Args[Idx].getKind()) {
+    case TemplateArgument::Type:
+      if (Args[Idx].getAsType()->isDependentType())
+        return true;
+      break;
+      
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      // Never dependent
+      break;
+
+    case TemplateArgument::Expression:
+      if (Args[Idx].getAsExpr()->isTypeDependent() ||
+          Args[Idx].getAsExpr()->isValueDependent())
+        return true;
+      break;
     }
-    Words[PW] = Word;
   }
+
+  return false;
 }
 
 ClassTemplateSpecializationType::
-ClassTemplateSpecializationType(TemplateDecl *T, unsigned NumArgs,
-                                uintptr_t *Args, bool *ArgIsType,
-                                QualType Canon)
-  : Type(ClassTemplateSpecialization, Canon, /*FIXME:Dependent=*/false),
-    Template(T), NumArgs(NumArgs) 
+ClassTemplateSpecializationType(TemplateDecl *T, const TemplateArgument *Args,
+                                unsigned NumArgs, QualType Canon)
+  : Type(ClassTemplateSpecialization, 
+         Canon.isNull()? QualType(this, 0) : Canon,
+         /*FIXME: Check for dependent template */
+         anyDependentTemplateArguments(Args, NumArgs)),
+    Template(T), NumArgs(NumArgs)
 {
-  uintptr_t *Data = reinterpret_cast<uintptr_t *>(this + 1);
+  assert((!Canon.isNull() || 
+          anyDependentTemplateArguments(Args, NumArgs)) &&
+         "No canonical type for non-dependent class template specialization");
 
-  // Pack the argument-is-type values into the words just after the
-  // class template specialization type.
-  packBooleanValues(NumArgs, ArgIsType, Data);
-
-  // Copy the template arguments after the packed words.
-  Data += getNumPackedWords(NumArgs);
+  TemplateArgument *TemplateArgs 
+    = reinterpret_cast<TemplateArgument *>(this + 1);
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-    Data[Arg] = Args[Arg];
+    new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
 }
 
 void ClassTemplateSpecializationType::Destroy(ASTContext& C) {
   for (unsigned Arg = 0; Arg < NumArgs; ++Arg)
-    if (!isArgType(Arg))
-      getArgAsExpr(Arg)->Destroy(C);
+    if (Expr *E = getArg(Arg).getAsExpr())
+      E->Destroy(C);
+}
+
+ClassTemplateSpecializationType::iterator
+ClassTemplateSpecializationType::end() const {
+  return begin() + getNumArgs();
 }
 
-uintptr_t
-ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
-  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
-  Data += getNumPackedWords(NumArgs);
-  return Data[Arg];
+const TemplateArgument &
+ClassTemplateSpecializationType::getArg(unsigned Idx) const {
+  assert(Idx < getNumArgs() && "Template argument out of range");
+  return getArgs()[Idx];
 }
 
-bool ClassTemplateSpecializationType::isArgType(unsigned Arg) const {
-  const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
-  const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
-  Data += Arg / BitsPerWord;
-  return (*Data >> ((NumArgs - Arg) % BitsPerWord - 1)) & 0x01;
+void 
+ClassTemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, 
+                                         TemplateDecl *T, 
+                                         const TemplateArgument *Args, 
+                                         unsigned NumArgs) {
+  ID.AddPointer(T);
+
+  for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
+    Args[Idx].Profile(ID);
 }
 
 //===----------------------------------------------------------------------===//
@@ -1280,11 +1298,24 @@ getAsStringInternal(std::string &InnerString) const {
     
     // Print the argument into a string.
     std::string ArgString;
-    if (isArgType(Arg))
-      getArgAsType(Arg).getAsStringInternal(ArgString);
-    else {
+    switch (getArg(Arg).getKind()) {
+    case TemplateArgument::Type:
+      getArg(Arg).getAsType().getAsStringInternal(ArgString);
+      break;
+
+    case TemplateArgument::Declaration:
+      ArgString = cast<NamedDecl>(getArg(Arg).getAsDecl())->getNameAsString();
+      break;
+
+    case TemplateArgument::Integral:
+      ArgString = getArg(Arg).getAsIntegral()->toString(10, true);
+      break;
+
+    case TemplateArgument::Expression: {
       llvm::raw_string_ostream s(ArgString);
-      getArgAsExpr(Arg)->printPretty(s);
+      getArg(Arg).getAsExpr()->printPretty(s);
+      break;
+    }
     }
 
     // If this is the first argument and its string representation
index b7a8f1a366dc454a90ad31323a1d107273282b21..1b9fed4866aef7e7e3186e173b9763e09bc4b75c 100644 (file)
@@ -390,13 +390,7 @@ void ClassTemplateSpecializationType::EmitImpl(Serializer& S) const {
   S.Emit(getCanonicalTypeInternal());
   S.EmitPtr(Template);
   S.EmitInt(NumArgs);
-  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
-    S.EmitBool(isArgType(Arg));
-    if (isArgType(Arg))
-      S.Emit(getArgAsType(Arg));
-    else
-      S.EmitOwnedPtr(getArgAsExpr(Arg));
-  }
+  // FIXME: Serialize class template specialization types
 }
 
 Type* 
@@ -409,19 +403,10 @@ CreateImpl(ASTContext& Context, Deserializer& D) {
   TemplateDecl *Template = cast<TemplateDecl>(D.ReadPtr<Decl>());
   unsigned NumArgs = D.ReadInt();
 
-  for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
-    bool IsType = D.ReadBool();
-    ArgIsType.push_back(IsType);
-    if (IsType)
-      Args.push_back(
-         reinterpret_cast<uintptr_t>(QualType::ReadVal(D).getAsOpaquePtr()));
-    else
-      Args.push_back(reinterpret_cast<uintptr_t>(D.ReadOwnedPtr<Expr>(Context)));
-  }
-
-  return Context.getClassTemplateSpecializationType(Template, NumArgs,
-                                                    &Args[0], &ArgIsType[0],
-                                                    Canon).getTypePtr();
+  // FIXME: De-serialize class template specialization types
+  (void)Template;
+  (void)NumArgs;
+  return 0;
 }
 
 //===----------------------------------------------------------------------===//
index 4ac8ffc0fb8e0cd051a42b073cd7481477797309..83be895909077c47ec25d3b073d808d2fae86bb2 100644 (file)
@@ -1601,6 +1601,13 @@ public:
                      AttributeList *Attr,
                      MultiTemplateParamsArg TemplateParameterLists);
 
+  QualType CheckClassTemplateId(ClassTemplateDecl *ClassTemplate,
+                                SourceLocation TemplateLoc,
+                                SourceLocation LAngleLoc,
+                                const TemplateArgument *TemplateArgs,
+                                unsigned NumTemplateArgs,
+                                SourceLocation RAngleLoc);
+
   virtual TypeResult
   ActOnClassTemplateId(DeclTy *Template, SourceLocation TemplateLoc,
                        SourceLocation LAngleLoc,
@@ -1630,8 +1637,8 @@ public:
   bool CheckTemplateArgumentList(TemplateDecl *Template,
                                  SourceLocation TemplateLoc,
                                  SourceLocation LAngleLoc,
-                                 ASTTemplateArgsPtr& TemplateArgs,
-                                 SourceLocation *TemplateArgLocs,
+                                 const TemplateArgument *TemplateArgs,
+                                 unsigned NumTemplateArgs,
                                  SourceLocation RAngleLoc,
                        llvm::SmallVectorImpl<TemplateArgument> &Converted);
 
index 7773b9e61500bc834d07c6bb12f401140cf89272..e9e2e3c2acec2a2f4834449ad41f23e393673f93 100644 (file)
@@ -383,7 +383,8 @@ Sema::BaseResult
 Sema::ActOnBaseSpecifier(DeclTy *classdecl, SourceRange SpecifierRange,
                          bool Virtual, AccessSpecifier Access,
                          TypeTy *basetype, SourceLocation BaseLoc) {
-  CXXRecordDecl *Class = (CXXRecordDecl*)classdecl;
+  AdjustDeclIfTemplate(classdecl);
+  CXXRecordDecl *Class = cast<CXXRecordDecl>((Decl*)classdecl);
   QualType BaseType = QualType::getFromOpaquePtr(basetype);
   if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
                                                       Virtual, Access,
index a55e3a5184578efeb8602c6c6181925415410f78..281984de2c9810864f021fb20f8bc884864080f1 100644 (file)
@@ -658,61 +658,115 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams,
   return Invalid;
 }
 
-Action::TypeResult
-Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc,
-                           SourceLocation LAngleLoc, 
-                           ASTTemplateArgsPtr TemplateArgs,
+/// \brief Translates template arguments as provided by the parser
+/// into template arguments used by semantic analysis.
+static void 
+translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, 
                            SourceLocation *TemplateArgLocs,
-                           SourceLocation RAngleLoc,
-                           const CXXScopeSpec *SS) {
-  TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
-  ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template);
+                     llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) {
+  TemplateArgs.reserve(TemplateArgsIn.size());
+
+  void **Args = TemplateArgsIn.getArgs();
+  bool *ArgIsType = TemplateArgsIn.getArgIsType();
+  for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) {
+    TemplateArgs.push_back(
+      ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg],
+                                       QualType::getFromOpaquePtr(Args[Arg]))
+                    : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg])));
+  }
+}
 
+QualType Sema::CheckClassTemplateId(ClassTemplateDecl *ClassTemplate,
+                                    SourceLocation TemplateLoc,
+                                    SourceLocation LAngleLoc,
+                                    const TemplateArgument *TemplateArgs,
+                                    unsigned NumTemplateArgs,
+                                    SourceLocation RAngleLoc) {
   // Check that the template argument list is well-formed for this
   // template.
   llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs;
-  if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, 
-                                TemplateArgs, TemplateArgLocs, RAngleLoc,
+  if (CheckTemplateArgumentList(ClassTemplate, TemplateLoc, LAngleLoc, 
+                                TemplateArgs, NumTemplateArgs, RAngleLoc,
                                 ConvertedTemplateArgs))
-    return true;
+    return QualType();
 
   assert((ConvertedTemplateArgs.size() == 
-            Template->getTemplateParameters()->size()) &&
+            ClassTemplate->getTemplateParameters()->size()) &&
          "Converted template argument list is too short!");
 
-  // Find the class template specialization declaration that
-  // corresponds to these arguments.
-  llvm::FoldingSetNodeID ID;
-  ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0],
-                                           ConvertedTemplateArgs.size());
-  void *InsertPos = 0;
-  ClassTemplateSpecializationDecl *Decl
-    = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
-  if (!Decl) {
-    // This is the first time we have referenced this class template
-    // specialization. Create the canonical declaration and add it to
-    // the set of specializations.
-    Decl = ClassTemplateSpecializationDecl::Create(Context, 
+  QualType CanonType;
+
+  if (ClassTemplateSpecializationType::anyDependentTemplateArguments(
+                                                      TemplateArgs,
+                                                      NumTemplateArgs)) {
+    // This class template specialization is a dependent
+    // type. Therefore, its canonical type is another class template
+    // specialization type that contains all of the converted
+    // arguments in canonical form. This ensures that, e.g., A<T> and
+    // A<T, T> have identical types when A is declared as:
+    //
+    //   template<typename T, typename U = T> struct A;
+
+    CanonType = Context.getClassTemplateSpecializationType(ClassTemplate, 
+                                                    &ConvertedTemplateArgs[0],
+                                                ConvertedTemplateArgs.size());
+  } else {
+    // Find the class template specialization declaration that
+    // corresponds to these arguments.
+    llvm::FoldingSetNodeID ID;
+    ClassTemplateSpecializationDecl::Profile(ID, &ConvertedTemplateArgs[0],
+                                             ConvertedTemplateArgs.size());
+    void *InsertPos = 0;
+    ClassTemplateSpecializationDecl *Decl
+      = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+    if (!Decl) {
+      // This is the first time we have referenced this class template
+      // specialization. Create the canonical declaration and add it to
+      // the set of specializations.
+      Decl = ClassTemplateSpecializationDecl::Create(Context, 
                                            ClassTemplate->getDeclContext(),
-                                                   TemplateLoc,
-                                                   ClassTemplate,
-                                                   &ConvertedTemplateArgs[0],
-                                                ConvertedTemplateArgs.size(),
-                                                   0);
-    ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
-    Decl->setLexicalDeclContext(CurContext);
+                                                     TemplateLoc,
+                                                     ClassTemplate,
+                                                     &ConvertedTemplateArgs[0],
+                                                  ConvertedTemplateArgs.size(),
+                                                     0);
+      ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
+      Decl->setLexicalDeclContext(CurContext);
+    }
+
+    CanonType = Context.getTypeDeclType(Decl);
   }
   
   // Build the fully-sugared type for this class template
   // specialization, which refers back to the class template
   // specialization we created or found.
-  QualType Result
-    = Context.getClassTemplateSpecializationType(Template, 
-                                                 TemplateArgs.size(),
-                    reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), 
-                                                 TemplateArgs.getArgIsType(),
-                                               Context.getTypeDeclType(Decl));
-  TemplateArgs.release();
+  return Context.getClassTemplateSpecializationType(ClassTemplate, 
+                                                    TemplateArgs,
+                                                    NumTemplateArgs, 
+                                                    CanonType);
+}
+
+Action::TypeResult
+Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc,
+                           SourceLocation LAngleLoc, 
+                           ASTTemplateArgsPtr TemplateArgsIn,
+                           SourceLocation *TemplateArgLocs,
+                           SourceLocation RAngleLoc,
+                           const CXXScopeSpec *SS) {
+  TemplateDecl *Template = cast<TemplateDecl>(static_cast<Decl *>(TemplateD));
+  ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Template);
+
+  // Translate the parser's template argument list in our AST format.
+  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+
+  QualType Result = CheckClassTemplateId(ClassTemplate, TemplateLoc,
+                                         LAngleLoc, 
+                                         &TemplateArgs[0],
+                                         TemplateArgs.size(),
+                                         RAngleLoc);
+
+  TemplateArgsIn.release();
   return Result.getAsOpaquePtr();
 }
 
@@ -721,13 +775,13 @@ Sema::ActOnClassTemplateId(DeclTy *TemplateD, SourceLocation TemplateLoc,
 bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
                                      SourceLocation TemplateLoc,
                                      SourceLocation LAngleLoc,
-                                     ASTTemplateArgsPtr& Args,
-                                     SourceLocation *TemplateArgLocs,
+                                     const TemplateArgument *TemplateArgs,
+                                     unsigned NumTemplateArgs,
                                      SourceLocation RAngleLoc,
                           llvm::SmallVectorImpl<TemplateArgument> &Converted) {
   TemplateParameterList *Params = Template->getTemplateParameters();
   unsigned NumParams = Params->size();
-  unsigned NumArgs = Args.size();
+  unsigned NumArgs = NumTemplateArgs;
   bool Invalid = false;
 
   if (NumArgs > NumParams ||
@@ -737,7 +791,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
     // arguments.
     SourceRange Range;
     if (NumArgs > NumParams)
-      Range = SourceRange(TemplateArgLocs[NumParams], RAngleLoc);
+      Range = SourceRange(TemplateArgs[NumParams].getLocation(), RAngleLoc);
     Diag(TemplateLoc, diag::err_template_arg_list_different_arity)
       << (NumArgs > NumParams)
       << (isa<ClassTemplateDecl>(Template)? 0 :
@@ -759,9 +813,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
                                        ParamEnd = Params->end();
        Param != ParamEnd; ++Param, ++ArgIdx) {
     // Decode the template argument
-    QualType ArgType;
-    Expr *ArgExpr = 0;
-    SourceLocation ArgLoc;
+    TemplateArgument Arg;
     if (ArgIdx >= NumArgs) {
       // Retrieve the default template argument from the template
       // parameter.
@@ -769,7 +821,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
         if (!TTP->hasDefaultArgument())
           break;
 
-        ArgType = TTP->getDefaultArgument();
+        QualType ArgType = TTP->getDefaultArgument();
 
         // If the argument type is dependent, instantiate it now based
         // on the previously-computed template arguments.
@@ -781,15 +833,14 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
         if (ArgType.isNull())
           return true;
 
-        ArgLoc = TTP->getDefaultArgumentLoc();
+        Arg = TemplateArgument(TTP->getLocation(), ArgType);
       } else if (NonTypeTemplateParmDecl *NTTP 
                    = dyn_cast<NonTypeTemplateParmDecl>(*Param)) {
         if (!NTTP->hasDefaultArgument())
           break;
 
         // FIXME: Instantiate default argument
-        ArgExpr = NTTP->getDefaultArgument();
-        ArgLoc = NTTP->getDefaultArgumentLoc();
+        Arg = TemplateArgument(NTTP->getDefaultArgument());
       } else {
         TemplateTemplateParmDecl *TempParm 
           = cast<TemplateTemplateParmDecl>(*Param);      
@@ -798,29 +849,24 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
           break;
 
         // FIXME: Instantiate default argument
-        ArgExpr = TempParm->getDefaultArgument();
-        ArgLoc = TempParm->getDefaultArgumentLoc();
+        Arg = TemplateArgument(TempParm->getDefaultArgument());
       }
     } else {
       // Retrieve the template argument produced by the user.
-      ArgLoc = TemplateArgLocs[ArgIdx];
-
-      if (Args.getArgIsType()[ArgIdx])
-        ArgType = QualType::getFromOpaquePtr(Args.getArgs()[ArgIdx]);
-      else
-        ArgExpr = reinterpret_cast<Expr *>(Args.getArgs()[ArgIdx]);
+      Arg = TemplateArgs[ArgIdx];
     }
 
 
     if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
       // Check template type parameters.
-      if (!ArgType.isNull()) {
-        if (CheckTemplateArgument(TTP, ArgType, ArgLoc))
+      if (Arg.getKind() == TemplateArgument::Type) {
+        if (CheckTemplateArgument(TTP, Arg.getAsType(), Arg.getLocation()))
           Invalid = true;
 
         // Add the converted template type argument.
         Converted.push_back(
-                      TemplateArgument(Context.getCanonicalType(ArgType)));
+                 TemplateArgument(Arg.getLocation(),
+                                  Context.getCanonicalType(Arg.getAsType())));
         continue;
       }
 
@@ -829,9 +875,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
       //   type shall be a type-id.
 
       // We have a template type parameter but the template argument
-      // is an expression.
-      Diag(ArgExpr->getSourceRange().getBegin(), 
-           diag::err_template_arg_must_be_type);
+      // is not a type.
+      Diag(Arg.getLocation(), diag::err_template_arg_must_be_type);
       Diag((*Param)->getLocation(), diag::note_template_param_here);
       Invalid = true;
     } else if (NonTypeTemplateParmDecl *NTTP 
@@ -859,50 +904,81 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
         }
       }
 
-      if (ArgExpr) {
-        if (CheckTemplateArgument(NTTP, NTTPType, ArgExpr, &Converted))
+      switch (Arg.getKind()) {
+      case TemplateArgument::Expression: {
+        Expr *E = Arg.getAsExpr();
+        if (CheckTemplateArgument(NTTP, NTTPType, E, &Converted))
           Invalid = true;
-        continue;
+        break;
       }
 
-      // We have a non-type template parameter but the template
-      // argument is a type.
-
-      // 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.
-      //
-      // We warn specifically about this case, since it can be rather
-      // confusing for users.
-      if (ArgType->isFunctionType())
-        Diag(ArgLoc, diag::err_template_arg_nontype_ambig)
-          << ArgType;
-      else
-        Diag(ArgLoc, diag::err_template_arg_must_be_expr);
-      Diag((*Param)->getLocation(), diag::note_template_param_here);
-      Invalid = true;
+      case TemplateArgument::Declaration:
+      case TemplateArgument::Integral:
+        // We've already checked this template argument, so just copy
+        // it to the list of converted arguments.
+        Converted.push_back(Arg);
+        break;
+
+      case TemplateArgument::Type:
+        // We have a non-type template parameter but the template
+        // argument is a type.
+        
+        // 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.
+        //
+        // We warn specifically about this case, since it can be rather
+        // confusing for users.
+        if (Arg.getAsType()->isFunctionType())
+          Diag(Arg.getLocation(), diag::err_template_arg_nontype_ambig)
+            << Arg.getAsType();
+        else
+          Diag(Arg.getLocation(), diag::err_template_arg_must_be_expr);
+        Diag((*Param)->getLocation(), diag::note_template_param_here);
+        Invalid = true;
+      }
     } else { 
       // Check template template parameters.
       TemplateTemplateParmDecl *TempParm 
         = cast<TemplateTemplateParmDecl>(*Param);
      
-      if (ArgExpr && isa<DeclRefExpr>(ArgExpr) &&
-          isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) {
-        if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr)))
-          Invalid = true;
-
-        // Add the converted template argument.
-        // FIXME: Need the "canonical" template declaration!
-        Converted.push_back(
-                   TemplateArgument(cast<DeclRefExpr>(ArgExpr)->getDecl()));
-        continue;
+      switch (Arg.getKind()) {
+      case TemplateArgument::Expression: {
+        Expr *ArgExpr = Arg.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.
+          // FIXME: Need the "canonical" template declaration!
+          Converted.push_back(
+                    TemplateArgument(Arg.getLocation(),
+                                     cast<DeclRefExpr>(ArgExpr)->getDecl()));
+          continue;
+        }
+      }
+        // fall through
+        
+      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;
       }
 
-      // We have a template template parameter but the template
-      // argument does not refer to a template.
-      Diag(ArgLoc, diag::err_template_arg_must_be_template);
-      Invalid = true;
+      case TemplateArgument::Declaration:
+        // We've already checked this template argument, so just copy
+        // it to the list of converted arguments.
+        Converted.push_back(Arg);
+        break;
+        
+      case TemplateArgument::Integral:
+        assert(false && "Integral argument with template template parameter");
+        break;
+      }
     }
   }
 
@@ -1109,11 +1185,16 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {
 bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                                  QualType InstantiatedParamType, Expr *&Arg, 
                          llvm::SmallVectorImpl<TemplateArgument> *Converted) {
+  SourceLocation StartLoc = Arg->getSourceRange().getBegin();
+
   // If either the parameter has a dependent type or the argument is
   // type-dependent, there's nothing we can check now.
   // FIXME: Add template argument to Converted!
-  if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent())
+  if (InstantiatedParamType->isDependentType() || Arg->isTypeDependent()) {
+    // FIXME: Produce a cloned, canonical expression?
+    Converted->push_back(TemplateArgument(Arg));
     return false;
+  }
 
   // C++ [temp.arg.nontype]p5:
   //   The following conversions are performed on each expression used
@@ -1188,7 +1269,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
                                IntegerType->isSignedIntegerType());
       CanonicalArg = Value;
 
-      Converted->push_back(TemplateArgument(CanonicalArg));
+      Converted->push_back(TemplateArgument(StartLoc, CanonicalArg));
     }
 
     return false;
@@ -1252,7 +1333,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
         return true;
 
       if (Converted)
-        Converted->push_back(TemplateArgument(Member));
+        Converted->push_back(TemplateArgument(StartLoc, Member));
 
       return false;
     }
@@ -1262,7 +1343,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       return true;
 
     if (Converted)
-      Converted->push_back(TemplateArgument(Entity));
+      Converted->push_back(TemplateArgument(StartLoc, Entity));
     return false;
   }
 
@@ -1297,7 +1378,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       return true;
 
     if (Converted)
-      Converted->push_back(TemplateArgument(Entity));
+      Converted->push_back(TemplateArgument(StartLoc, Entity));
 
     return false;
   }
@@ -1339,7 +1420,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
       return true;
 
     if (Converted)
-      Converted->push_back(TemplateArgument(Entity));
+      Converted->push_back(TemplateArgument(StartLoc, Entity));
 
     return false;
   }
@@ -1366,7 +1447,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,
     return true;
   
   if (Converted)
-    Converted->push_back(TemplateArgument(Member));
+    Converted->push_back(TemplateArgument(StartLoc, Member));
   
   return false;
 }
@@ -1649,7 +1730,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
                                        DeclTy *TemplateD,
                                        SourceLocation TemplateNameLoc,
                                        SourceLocation LAngleLoc,
-                                       ASTTemplateArgsPtr TemplateArgs,
+                                       ASTTemplateArgsPtr TemplateArgsIn,
                                        SourceLocation *TemplateArgLocs,
                                        SourceLocation RAngleLoc,
                                        AttributeList *Attr,
@@ -1701,12 +1782,16 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
     Kind = ClassTemplate->getTemplatedDecl()->getTagKind();
   }
 
+  // Translate the parser's template argument list in our AST format.
+  llvm::SmallVector<TemplateArgument, 16> TemplateArgs;
+  translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);
+
   // Check that the template argument list is well-formed for this
   // template.
   llvm::SmallVector<TemplateArgument, 16> ConvertedTemplateArgs;
   if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, 
-                                TemplateArgs, TemplateArgLocs, RAngleLoc,
-                                ConvertedTemplateArgs))
+                                &TemplateArgs[0], TemplateArgs.size(),
+                                RAngleLoc, ConvertedTemplateArgs))
     return 0;
 
   assert((ConvertedTemplateArgs.size() == 
@@ -1786,11 +1871,10 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
   // template arguments in the specialization.
   Specialization->setTypeAsWritten(
     Context.getClassTemplateSpecializationType(ClassTemplate, 
+                                               &TemplateArgs[0],
                                                TemplateArgs.size(),
-                  reinterpret_cast<uintptr_t *>(TemplateArgs.getArgs()), 
-                                               TemplateArgs.getArgIsType(),
                                   Context.getTypeDeclType(Specialization)));
-  TemplateArgs.release();
+  TemplateArgsIn.release();
 
   // C++ [temp.expl.spec]p9:
   //   A template explicit specialization is in the scope of the
index faeebc0680833b60a02a0310e55ecf41219f0394..71bba49af9d5d8272fa9229af57036679fd0d3f0 100644 (file)
@@ -302,9 +302,44 @@ TemplateTypeInstantiator::
 InstantiateClassTemplateSpecializationType(
                                   const ClassTemplateSpecializationType *T,
                                   unsigned Quals) const {
-  // FIXME: Implement this
-  assert(false && "Cannot instantiate ClassTemplateSpecializationType yet");
-  return QualType();
+  llvm::SmallVector<TemplateArgument, 16> InstantiatedTemplateArgs;
+  InstantiatedTemplateArgs.reserve(T->getNumArgs());
+  for (ClassTemplateSpecializationType::iterator Arg = T->begin(), 
+                                              ArgEnd = T->end();
+       Arg != ArgEnd; ++Arg) {
+    switch (Arg->getKind()) {
+    case TemplateArgument::Type: {
+      QualType T = SemaRef.InstantiateType(Arg->getAsType(), 
+                                           TemplateArgs, NumTemplateArgs,
+                                           Arg->getLocation(),
+                                           DeclarationName());
+      if (T.isNull())
+        return QualType();
+
+      InstantiatedTemplateArgs.push_back(
+                                TemplateArgument(Arg->getLocation(), T));
+      break;
+    }
+
+    case TemplateArgument::Declaration:
+    case TemplateArgument::Integral:
+      InstantiatedTemplateArgs.push_back(*Arg);
+      break;
+
+    case TemplateArgument::Expression:
+      assert(false && "Cannot instantiate expressions yet");
+      break;
+    }
+  }
+
+  // FIXME: We're missing the locations of the template name, '<', and
+  // '>'.
+  return SemaRef.CheckClassTemplateId(cast<ClassTemplateDecl>(T->getTemplate()),
+                                      Loc,
+                                      SourceLocation(),
+                                      &InstantiatedTemplateArgs[0],
+                                      InstantiatedTemplateArgs.size(),
+                                      SourceLocation());
 }
 
 QualType 
index 216a283e2e99c272826965dff9382ea21a51b1e9..94e4505f40549be672e0bc866dbe272a884d46ff 100644 (file)
@@ -14,8 +14,7 @@ A<A<int> > *a6;
 // [temp.arg.type]p2
 void f() {
   class X { };
-  A<X> * a = 0; // expected-error{{template argument uses local type 'class X'}} \
-                // FIXME: expected-error{{use of undeclared identifier 'a'}}
+  A<X> * a = 0; // expected-error{{template argument uses local type 'class X'}}
 }
 
 struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}}