Implement template instantiation for ClassTemplateSpecializationTypes,
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
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 3b06b4e..412b0cf 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -921,59 +921,77 @@
return isa<EnumDecl>(TT->getDecl());
}
-void
+bool
ClassTemplateSpecializationType::
-packBooleanValues(unsigned NumArgs, bool *Values, uintptr_t *Words) {
- const unsigned BitsPerWord = sizeof(uintptr_t) * 8;
+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;
- 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];
+ 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);
}
-uintptr_t
-ClassTemplateSpecializationType::getArgAsOpaqueValue(unsigned Arg) const {
- const uintptr_t *Data = reinterpret_cast<const uintptr_t *>(this + 1);
- Data += getNumPackedWords(NumArgs);
- return Data[Arg];
+ClassTemplateSpecializationType::iterator
+ClassTemplateSpecializationType::end() const {
+ return begin() + getNumArgs();
}
-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;
+const TemplateArgument &
+ClassTemplateSpecializationType::getArg(unsigned Idx) const {
+ assert(Idx < getNumArgs() && "Template argument out of range");
+ return getArgs()[Idx];
+}
+
+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 @@
// 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