Use the new statement/expression profiling code to unique dependent

template arguments, as in template specialization types. This permits
matching out-of-line definitions of members for class templates that
involve non-type template parameters.

llvm-svn: 77462
This commit is contained in:
Douglas Gregor 2009-07-29 16:09:57 +00:00
parent ea2f1ceb4b
commit 0004417e81
9 changed files with 63 additions and 28 deletions

View File

@ -315,7 +315,7 @@ public:
void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
/// \brief Used to insert TemplateArguments into FoldingSets. /// \brief Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID) const { void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) const {
ID.AddInteger(Kind); ID.AddInteger(Kind);
switch (Kind) { switch (Kind) {
case Null: case Null:
@ -326,7 +326,7 @@ public:
break; break;
case Declaration: case Declaration:
ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! ID.AddPointer(getAsDecl()? getAsDecl()->getCanonicalDecl() : 0);
break; break;
case Integral: case Integral:
@ -335,14 +335,13 @@ public:
break; break;
case Expression: case Expression:
// FIXME: We need a canonical representation of expressions. getAsExpr()->Profile(ID, Context, true);
ID.AddPointer(getAsExpr());
break; break;
case Pack: case Pack:
ID.AddInteger(Args.NumArgs); ID.AddInteger(Args.NumArgs);
for (unsigned I = 0; I != Args.NumArgs; ++I) for (unsigned I = 0; I != Args.NumArgs; ++I)
Args.Args[I].Profile(ID); Args.Args[I].Profile(ID, Context);
} }
} }
}; };
@ -534,15 +533,16 @@ public:
void Profile(llvm::FoldingSetNodeID &ID) { void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, TemplateArguments->getFlatArgumentList(), Profile(ID, TemplateArguments->getFlatArgumentList(),
TemplateArguments->flat_size()); TemplateArguments->flat_size(),
Function->getASTContext());
} }
static void static void
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) { unsigned NumTemplateArgs, ASTContext &Context) {
ID.AddInteger(NumTemplateArgs); ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
TemplateArgs[Arg].Profile(ID); TemplateArgs[Arg].Profile(ID, Context);
} }
}; };
@ -918,15 +918,16 @@ public:
} }
void Profile(llvm::FoldingSetNodeID &ID) const { void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size()); Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(),
getASTContext());
} }
static void static void
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) { unsigned NumTemplateArgs, ASTContext &Context) {
ID.AddInteger(NumTemplateArgs); ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
TemplateArgs[Arg].Profile(ID); TemplateArgs[Arg].Profile(ID, Context);
} }
static bool classof(const Decl *D) { static bool classof(const Decl *D) {

View File

@ -1782,14 +1782,18 @@ public:
class TemplateSpecializationType class TemplateSpecializationType
: public Type, public llvm::FoldingSetNode { : public Type, public llvm::FoldingSetNode {
/// \brief The name of the template being specialized. // FIXME: Currently needed for profiling expressions; can we avoid this?
ASTContext &Context;
/// \brief The name of the template being specialized.
TemplateName Template; TemplateName Template;
/// \brief - The number of template arguments named in this class /// \brief - The number of template arguments named in this class
/// template specialization. /// template specialization.
unsigned NumArgs; unsigned NumArgs;
TemplateSpecializationType(TemplateName T, TemplateSpecializationType(ASTContext &Context,
TemplateName T,
const TemplateArgument *Args, const TemplateArgument *Args,
unsigned NumArgs, QualType Canon); unsigned NumArgs, QualType Canon);
@ -1833,11 +1837,12 @@ public:
const PrintingPolicy &Policy) const; const PrintingPolicy &Policy) const;
void Profile(llvm::FoldingSetNodeID &ID) { void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Template, getArgs(), NumArgs); Profile(ID, Template, getArgs(), NumArgs, Context);
} }
static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T,
const TemplateArgument *Args, unsigned NumArgs); const TemplateArgument *Args, unsigned NumArgs,
ASTContext &Context);
static bool classof(const Type *T) { static bool classof(const Type *T) {
return T->getTypeClass() == TemplateSpecialization; return T->getTypeClass() == TemplateSpecialization;

View File

@ -1682,7 +1682,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
// exists. // exists.
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
TemplateSpecializationType::Profile(ID, CanonTemplate, TemplateSpecializationType::Profile(ID, CanonTemplate,
CanonArgs.data(), NumArgs); CanonArgs.data(), NumArgs, *this);
void *InsertPos = 0; void *InsertPos = 0;
TemplateSpecializationType *Spec TemplateSpecializationType *Spec
@ -1693,7 +1693,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
void *Mem = Allocate((sizeof(TemplateSpecializationType) + void *Mem = Allocate((sizeof(TemplateSpecializationType) +
sizeof(TemplateArgument) * NumArgs), sizeof(TemplateArgument) * NumArgs),
8); 8);
Spec = new (Mem) TemplateSpecializationType(CanonTemplate, Spec = new (Mem) TemplateSpecializationType(*this, CanonTemplate,
CanonArgs.data(), NumArgs, CanonArgs.data(), NumArgs,
QualType()); QualType());
Types.push_back(Spec); Types.push_back(Spec);
@ -1713,7 +1713,8 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
sizeof(TemplateArgument) * NumArgs), sizeof(TemplateArgument) * NumArgs),
8); 8);
TemplateSpecializationType *Spec TemplateSpecializationType *Spec
= new (Mem) TemplateSpecializationType(Template, Args, NumArgs, Canon); = new (Mem) TemplateSpecializationType(*this, Template, Args, NumArgs,
Canon);
Types.push_back(Spec); Types.push_back(Spec);
return QualType(Spec, 0); return QualType(Spec, 0);

View File

@ -107,6 +107,10 @@ void StmtProfiler::VisitIfStmt(IfStmt *S) {
VisitStmt(S); VisitStmt(S);
} }
void StmtProfiler::VisitSwitchStmt(SwitchStmt *S) {
VisitStmt(S);
}
void StmtProfiler::VisitWhileStmt(WhileStmt *S) { void StmtProfiler::VisitWhileStmt(WhileStmt *S) {
VisitStmt(S); VisitStmt(S);
} }
@ -330,6 +334,10 @@ void StmtProfiler::VisitGNUNullExpr(GNUNullExpr *S) {
VisitExpr(S); VisitExpr(S);
} }
void StmtProfiler::VisitVAArgExpr(VAArgExpr *S) {
VisitExpr(S);
}
void StmtProfiler::VisitInitListExpr(InitListExpr *S) { void StmtProfiler::VisitInitListExpr(InitListExpr *S) {
if (S->getSyntacticForm()) { if (S->getSyntacticForm()) {
VisitInitListExpr(S->getSyntacticForm()); VisitInitListExpr(S->getSyntacticForm());
@ -416,6 +424,10 @@ void StmtProfiler::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *S) {
ID.AddBoolean(S->getValue()); ID.AddBoolean(S->getValue());
} }
void StmtProfiler::VisitCXXNullPtrLiteralExpr(CXXNullPtrLiteralExpr *S) {
VisitExpr(S);
}
void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) { void StmtProfiler::VisitCXXTypeidExpr(CXXTypeidExpr *S) {
VisitExpr(S); VisitExpr(S);
if (S->isTypeOperand()) if (S->isTypeOperand())
@ -595,6 +607,7 @@ void StmtProfiler::VisitDecl(Decl *D) {
= dyn_cast_or_null<NonTypeTemplateParmDecl>(D)) { = dyn_cast_or_null<NonTypeTemplateParmDecl>(D)) {
ID.AddInteger(NTTP->getDepth()); ID.AddInteger(NTTP->getDepth());
ID.AddInteger(NTTP->getIndex()); ID.AddInteger(NTTP->getIndex());
VisitType(NTTP->getType());
return; return;
} }

View File

@ -1033,11 +1033,13 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned NumArgs) {
} }
TemplateSpecializationType:: TemplateSpecializationType::
TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, TemplateSpecializationType(ASTContext &Context, TemplateName T,
const TemplateArgument *Args,
unsigned NumArgs, QualType Canon) unsigned NumArgs, QualType Canon)
: Type(TemplateSpecialization, : Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon, Canon.isNull()? QualType(this, 0) : Canon,
T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)), T.isDependent() || anyDependentTemplateArguments(Args, NumArgs)),
Context(Context),
Template(T), NumArgs(NumArgs) Template(T), NumArgs(NumArgs)
{ {
assert((!Canon.isNull() || assert((!Canon.isNull() ||
@ -1074,10 +1076,11 @@ void
TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
TemplateName T, TemplateName T,
const TemplateArgument *Args, const TemplateArgument *Args,
unsigned NumArgs) { unsigned NumArgs,
ASTContext &Context) {
T.Profile(ID); T.Profile(ID);
for (unsigned Idx = 0; Idx < NumArgs; ++Idx) for (unsigned Idx = 0; Idx < NumArgs; ++Idx)
Args[Idx].Profile(ID); Args[Idx].Profile(ID, Context);
} }
const Type *QualifierSet::strip(const Type* T) { const Type *QualifierSet::strip(const Type* T) {

View File

@ -930,7 +930,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID, ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(), Converted.getFlatArguments(),
Converted.flatSize()); Converted.flatSize(),
Context);
void *InsertPos = 0; void *InsertPos = 0;
ClassTemplateSpecializationDecl *Decl ClassTemplateSpecializationDecl *Decl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
@ -2433,12 +2434,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// FIXME: Template parameter list matters, too // FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID, ClassTemplatePartialSpecializationDecl::Profile(ID,
Converted.getFlatArguments(), Converted.getFlatArguments(),
Converted.flatSize()); Converted.flatSize(),
Context);
} }
else else
ClassTemplateSpecializationDecl::Profile(ID, ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(), Converted.getFlatArguments(),
Converted.flatSize()); Converted.flatSize(),
Context);
void *InsertPos = 0; void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl = 0; ClassTemplateSpecializationDecl *PrevDecl = 0;
@ -2703,7 +2706,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID, ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(), Converted.getFlatArguments(),
Converted.flatSize()); Converted.flatSize(),
Context);
void *InsertPos = 0; void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);

View File

@ -321,7 +321,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
llvm::FoldingSetNodeID ID; llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID, FunctionTemplateSpecializationInfo::Profile(ID,
TemplateArgs.getFlatArgumentList(), TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size()); TemplateArgs.flat_size(),
SemaRef.Context);
FunctionTemplateSpecializationInfo *Info FunctionTemplateSpecializationInfo *Info
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,

View File

@ -1,5 +1,4 @@
// RUN: clang-cc -fsyntax-only -verify %s // RUN: clang-cc -fsyntax-only -verify %s
// XFAIL
template<int N, int M> template<int N, int M>
struct A0 { struct A0 {

View File

@ -19,7 +19,7 @@ X<float>::X<int> xi = x;
// [temp.local]p1: // [temp.local]p1:
// FIXME: test non-type and template template parameters // FIXME: test template template parameters
template<typename T, typename U> template<typename T, typename U>
struct X0 { struct X0 {
typedef T type; typedef T type;
@ -38,3 +38,11 @@ struct X0 {
void f2(X0&); void f2(X0&);
void f2(const ::X0<type, U_type2>&); // expected-error{{redecl}} void f2(const ::X0<type, U_type2>&); // expected-error{{redecl}}
}; };
template<typename T, T N>
struct X1 {
void f0(const X1&); // expected-note{{here}}
void f0(X1&);
void f0(const X1<T, N>&); // expected-error{{redecl}}
};