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/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 4579fb5..a51f432 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1309,14 +1309,15 @@
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 @@
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);
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index ed4fd44..ac76c25 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -145,6 +145,15 @@
}
//===----------------------------------------------------------------------===//
+// TemplateArgument Implementation
+//===----------------------------------------------------------------------===//
+
+TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(E);
+ StartLoc = E->getSourceRange().getBegin();
+}
+
+//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
ClassTemplateSpecializationDecl::
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
diff --git a/lib/AST/TypeSerialization.cpp b/lib/AST/TypeSerialization.cpp
index b7a8f1a..1b9fed4 100644
--- a/lib/AST/TypeSerialization.cpp
+++ b/lib/AST/TypeSerialization.cpp
@@ -390,13 +390,7 @@
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 @@
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;
}
//===----------------------------------------------------------------------===//