Keep track of function template specializations, to eliminate

redundant, implicit instantiations of function templates and provide a
place where we can hang function template specializations.

llvm-svn: 74454
This commit is contained in:
Douglas Gregor 2009-06-29 20:59:39 +00:00
parent 10de9e6602
commit 8f5d4423ca
9 changed files with 530 additions and 382 deletions

View File

@ -809,9 +809,7 @@ public:
return PreviousDeclaration;
}
void setPreviousDeclaration(FunctionDecl * PrevDecl) {
PreviousDeclaration = PrevDecl;
}
void setPreviousDeclaration(FunctionDecl * PrevDecl);
unsigned getBuiltinID(ASTContext &Context) const;
@ -961,7 +959,8 @@ public:
/// function template specialization from the template.
void setFunctionTemplateSpecialization(ASTContext &Context,
FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs);
const TemplateArgumentList *TemplateArgs,
void *InsertPos);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {

View File

@ -100,327 +100,6 @@ public:
}
};
//===----------------------------------------------------------------------===//
// Kinds of Templates
//===----------------------------------------------------------------------===//
/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
/// class, function, etc.). The TemplateDecl class stores the list of template
/// parameters and a reference to the templated scoped declaration: the
/// underlying AST node.
class TemplateDecl : public NamedDecl {
protected:
// This is probably never used.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0)
{ }
// Construct a template decl with the given name and parameters.
// Used when there is not templated element (tt-params, alias?).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params)
{ }
// Construct a template decl with name, parameters, and templated element.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { }
public:
~TemplateDecl();
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
}
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast;
}
static bool classof(const TemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
protected:
NamedDecl *TemplatedDecl;
TemplateParameterList* TemplateParams;
};
/// \brief Provides information about a function template specialization,
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo {
public:
FunctionTemplateDecl *Template;
const TemplateArgumentList *TemplateArguments;
};
/// Declaration of a template function.
class FunctionTemplateDecl : public TemplateDecl {
protected:
/// \brief Data that is common to all of the declarations of a given
/// class template.
struct Common {
/// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
/// \brief The class template partial specializations for this class
/// template.
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
PartialSpecializations;
/// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType;
};
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { }
public:
/// Get the underling function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
}
/// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl);
// Implement isa/cast/dyncast support
static bool classof(const Decl *D)
{ return D->getKind() == FunctionTemplate; }
static bool classof(const FunctionTemplateDecl *D)
{ return true; }
};
//===----------------------------------------------------------------------===//
// Kinds of Template Parameters
//===----------------------------------------------------------------------===//
/// The TemplateParmPosition class defines the position of a template parameter
/// within a template parameter list. Because template parameter can be listed
/// sequentially for out-of-line template members, each template parameter is
/// given a Depth - the nesting of template parameter scopes - and a Position -
/// the occurrence within the parameter list.
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition
{
protected:
// FIXME: This should probably never be called, but it's here as
TemplateParmPosition()
: Depth(0), Position(0)
{ /* assert(0 && "Cannot create positionless template parameter"); */ }
TemplateParmPosition(unsigned D, unsigned P)
: Depth(D), Position(P)
{ }
// FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
// position? Maybe?
unsigned Depth;
unsigned Position;
public:
/// Get the nesting depth of the template parameter.
unsigned getDepth() const { return Depth; }
/// Get the position of the template parameter within its parameter list.
unsigned getPosition() const { return Position; }
/// Get the index of the template parameter within its parameter list.
unsigned getIndex() const { return Position; }
};
/// TemplateTypeParmDecl - Declaration of a template type parameter,
/// e.g., "T" in
/// @code
/// template<typename T> class vector;
/// @endcode
class TemplateTypeParmDecl : public TypeDecl {
/// \brief Whether this template type parameter was declaration with
/// the 'typename' keyword. If false, it was declared with the
/// 'class' keyword.
bool Typename : 1;
/// \brief Whether this template type parameter inherited its
/// default argument.
bool InheritedDefault : 1;
/// \brief Whether this is a parameter pack.
bool ParameterPack : 1;
/// \brief The location of the default argument, if any.
SourceLocation DefaultArgumentLoc;
/// \brief The default template argument, if any.
QualType DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
TypeForDecl = Type.getTypePtr();
}
public:
static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
/// \brief Whether this template type parameter was declared with
/// the 'typename' keyword. If not, it was declared with the 'class'
/// keyword.
bool wasDeclaredWithTypename() const { return Typename; }
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
/// \brief Retrieve the default argument, if any.
QualType getDefaultArgument() const { return DefaultArgument; }
/// \brief Retrieve the location of the default argument, if any.
SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
/// \brief Determines whether the default argument was inherited
/// from a previous declaration of this template.
bool defaultArgumentWasInherited() const { return InheritedDefault; }
/// \brief Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
bool Inherited) {
DefaultArgument = DefArg;
DefaultArgumentLoc = DefArgLoc;
InheritedDefault = Inherited;
}
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const { return ParameterPack; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTypeParm;
}
static bool classof(const TemplateTypeParmDecl *D) { return true; }
};
/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
/// e.g., "Size" in
/// @code
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl
: public VarDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
Expr *DefaultArgument;
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
SourceLocation TSSL = SourceLocation())
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL),
TemplateParmPosition(D, P), DefaultArgument(0)
{ }
public:
static NonTypeTemplateParmDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
SourceLocation TypeSpecStartLoc = SourceLocation());
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
/// \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;
/// \brief Set the default argument for this template parameter.
void setDefaultArgument(Expr *DefArg) {
DefaultArgument = DefArg;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == NonTypeTemplateParm;
}
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
};
/// TemplateTemplateParmDecl - Declares a template template parameter,
/// e.g., "T" in
/// @code
/// template <template <typename> class T> class container { };
/// @endcode
/// A template template parameter is a TemplateDecl because it defines the
/// name of a template and the template parameters allowable for substitution.
class TemplateTemplateParmDecl
: public TemplateDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
Expr *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)
{ }
public:
static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id,
TemplateParameterList *Params);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
/// \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;
/// \brief Set the default argument for this template parameter.
void setDefaultArgument(Expr *DefArg) {
DefaultArgument = DefArg;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTemplateParm;
}
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
};
/// \brief Represents a template argument within a class template
/// specialization.
class TemplateArgument {
@ -767,6 +446,379 @@ public:
}
};
//===----------------------------------------------------------------------===//
// Kinds of Templates
//===----------------------------------------------------------------------===//
/// TemplateDecl - The base class of all kinds of template declarations (e.g.,
/// class, function, etc.). The TemplateDecl class stores the list of template
/// parameters and a reference to the templated scoped declaration: the
/// underlying AST node.
class TemplateDecl : public NamedDecl {
protected:
// This is probably never used.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(0)
{ }
// Construct a template decl with the given name and parameters.
// Used when there is not templated element (tt-params, alias?).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(0), TemplateParams(Params)
{ }
// Construct a template decl with name, parameters, and templated element.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
TemplateParams(Params) { }
public:
~TemplateDecl();
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
}
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TemplateFirst && D->getKind() <= TemplateLast;
}
static bool classof(const TemplateDecl *D) { return true; }
static bool classof(const FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
protected:
NamedDecl *TemplatedDecl;
TemplateParameterList* TemplateParams;
};
/// \brief Provides information about a function template specialization,
/// which is a FunctionDecl that has been explicitly specialization or
/// instantiated from a function template.
class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode {
public:
/// \brief The function template specialization that this structure
/// describes.
FunctionDecl *Function;
/// \brief The function template from which this function template
/// specialization was generated.
FunctionTemplateDecl *Template;
/// \brief The template arguments used to produce the function template
/// specialization from the function template.
const TemplateArgumentList *TemplateArguments;
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, TemplateArguments->getFlatArgumentList(),
TemplateArguments->flat_size());
}
static void
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
unsigned NumTemplateArgs) {
ID.AddInteger(NumTemplateArgs);
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
TemplateArgs[Arg].Profile(ID);
}
};
/// Declaration of a template function.
class FunctionTemplateDecl : public TemplateDecl {
protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common {
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
};
/// \brief A pointer to the previous declaration (if this is a redeclaration)
/// or to the data that is common to all declarations of this function
/// template.
llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev;
/// \brief Retrieves the "common" pointer shared by all
/// (re-)declarations of the same function template. Calling this routine
/// may implicitly allocate memory for the common pointer.
Common *getCommonPtr();
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
CommonOrPrev((Common*)0) { }
public:
void Destroy(ASTContext &C);
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
}
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDeclaration() {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Set the previous declaration of this function template.
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
if (Prev)
CommonOrPrev = Prev;
}
/// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
NamedDecl *Decl);
// Implement isa/cast/dyncast support
static bool classof(const Decl *D)
{ return D->getKind() == FunctionTemplate; }
static bool classof(const FunctionTemplateDecl *D)
{ return true; }
};
//===----------------------------------------------------------------------===//
// Kinds of Template Parameters
//===----------------------------------------------------------------------===//
/// The TemplateParmPosition class defines the position of a template parameter
/// within a template parameter list. Because template parameter can be listed
/// sequentially for out-of-line template members, each template parameter is
/// given a Depth - the nesting of template parameter scopes - and a Position -
/// the occurrence within the parameter list.
/// This class is inheritedly privately by different kinds of template
/// parameters and is not part of the Decl hierarchy. Just a facility.
class TemplateParmPosition
{
protected:
// FIXME: This should probably never be called, but it's here as
TemplateParmPosition()
: Depth(0), Position(0)
{ /* assert(0 && "Cannot create positionless template parameter"); */ }
TemplateParmPosition(unsigned D, unsigned P)
: Depth(D), Position(P)
{ }
// FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
// position? Maybe?
unsigned Depth;
unsigned Position;
public:
/// Get the nesting depth of the template parameter.
unsigned getDepth() const { return Depth; }
/// Get the position of the template parameter within its parameter list.
unsigned getPosition() const { return Position; }
/// Get the index of the template parameter within its parameter list.
unsigned getIndex() const { return Position; }
};
/// TemplateTypeParmDecl - Declaration of a template type parameter,
/// e.g., "T" in
/// @code
/// template<typename T> class vector;
/// @endcode
class TemplateTypeParmDecl : public TypeDecl {
/// \brief Whether this template type parameter was declaration with
/// the 'typename' keyword. If false, it was declared with the
/// 'class' keyword.
bool Typename : 1;
/// \brief Whether this template type parameter inherited its
/// default argument.
bool InheritedDefault : 1;
/// \brief Whether this is a parameter pack.
bool ParameterPack : 1;
/// \brief The location of the default argument, if any.
SourceLocation DefaultArgumentLoc;
/// \brief The default template argument, if any.
QualType DefaultArgument;
TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
bool Typename, QualType Type, bool ParameterPack)
: TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename),
InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() {
TypeForDecl = Type.getTypePtr();
}
public:
static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D, unsigned P,
IdentifierInfo *Id, bool Typename,
bool ParameterPack);
/// \brief Whether this template type parameter was declared with
/// the 'typename' keyword. If not, it was declared with the 'class'
/// keyword.
bool wasDeclaredWithTypename() const { return Typename; }
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
/// \brief Retrieve the default argument, if any.
QualType getDefaultArgument() const { return DefaultArgument; }
/// \brief Retrieve the location of the default argument, if any.
SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
/// \brief Determines whether the default argument was inherited
/// from a previous declaration of this template.
bool defaultArgumentWasInherited() const { return InheritedDefault; }
/// \brief Set the default argument for this template parameter, and
/// whether that default argument was inherited from another
/// declaration.
void setDefaultArgument(QualType DefArg, SourceLocation DefArgLoc,
bool Inherited) {
DefaultArgument = DefArg;
DefaultArgumentLoc = DefArgLoc;
InheritedDefault = Inherited;
}
/// \brief Returns whether this is a parameter pack.
bool isParameterPack() const { return ParameterPack; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTypeParm;
}
static bool classof(const TemplateTypeParmDecl *D) { return true; }
};
/// NonTypeTemplateParmDecl - Declares a non-type template parameter,
/// e.g., "Size" in
/// @code
/// template<int Size> class array { };
/// @endcode
class NonTypeTemplateParmDecl
: public VarDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
Expr *DefaultArgument;
NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
SourceLocation TSSL = SourceLocation())
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, VarDecl::None, TSSL),
TemplateParmPosition(D, P), DefaultArgument(0)
{ }
public:
static NonTypeTemplateParmDecl *
Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, QualType T,
SourceLocation TypeSpecStartLoc = SourceLocation());
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
/// \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;
/// \brief Set the default argument for this template parameter.
void setDefaultArgument(Expr *DefArg) {
DefaultArgument = DefArg;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == NonTypeTemplateParm;
}
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
};
/// TemplateTemplateParmDecl - Declares a template template parameter,
/// e.g., "T" in
/// @code
/// template <template <typename> class T> class container { };
/// @endcode
/// A template template parameter is a TemplateDecl because it defines the
/// name of a template and the template parameters allowable for substitution.
class TemplateTemplateParmDecl
: public TemplateDecl, protected TemplateParmPosition {
/// \brief The default template argument, if any.
Expr *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)
{ }
public:
static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id,
TemplateParameterList *Params);
using TemplateParmPosition::getDepth;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::getIndex;
/// \brief Determine whether this template parameter has a default
/// argument.
bool hasDefaultArgument() const { return DefaultArgument; }
/// \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;
/// \brief Set the default argument for this template parameter.
void setDefaultArgument(Expr *DefArg) {
DefaultArgument = DefArg;
}
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() == TemplateTemplateParm;
}
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
};
// \brief Describes the kind of template specialization that a
// particular template specialization declaration represents.
enum TemplateSpecializationKind {

View File

@ -1806,6 +1806,12 @@ Decl *ASTContext::getCanonicalDecl(Decl *D) {
return const_cast<FunctionDecl *>(Function);
}
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) {
while (FunTmpl->getPreviousDeclaration())
FunTmpl = FunTmpl->getPreviousDeclaration();
return FunTmpl;
}
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
while (Var->getPreviousDeclaration())
Var = Var->getPreviousDeclaration();

View File

@ -372,11 +372,6 @@ void FunctionDecl::Destroy(ASTContext& C) {
C.Deallocate(ParamInfo);
if (FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization
.dyn_cast<FunctionTemplateSpecializationInfo*>())
C.Deallocate(Info);
Decl::Destroy(C);
}
@ -564,6 +559,18 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const {
return false;
}
void
FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) {
PreviousDeclaration = PrevDecl;
if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) {
FunctionTemplateDecl *PrevFunTmpl
= PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0;
assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch");
FunTmpl->setPreviousDeclaration(PrevFunTmpl);
}
}
/// getOverloadedOperator - Which C++ overloaded operator this
/// function represents, if any.
OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const {
@ -595,15 +602,21 @@ FunctionDecl::getTemplateSpecializationArgs() const {
void
FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context,
FunctionTemplateDecl *Template,
const TemplateArgumentList *TemplateArgs) {
const TemplateArgumentList *TemplateArgs,
void *InsertPos) {
FunctionTemplateSpecializationInfo *Info
= TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>();
if (!Info)
Info = new (Context) FunctionTemplateSpecializationInfo;
Info->Function = this;
Info->Template = Template;
Info->TemplateArguments = TemplateArgs;
TemplateOrSpecialization = Info;
// Insert this function template specialization into the set of known
// function template specialiations.
Template->getSpecializations().InsertNode(Info, InsertPos);
}
//===----------------------------------------------------------------------===//

View File

@ -86,6 +86,31 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl);
}
void FunctionTemplateDecl::Destroy(ASTContext &C) {
if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) {
for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator
Spec = CommonPtr->Specializations.begin(),
SpecEnd = CommonPtr->Specializations.end();
Spec != SpecEnd; ++Spec)
C.Deallocate(&*Spec);
}
Decl::Destroy(C);
}
FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
// Find the first declaration of this function template.
FunctionTemplateDecl *First = this;
while (First->getPreviousDeclaration())
First = First->getPreviousDeclaration();
if (First->CommonOrPrev.isNull()) {
// FIXME: Allocate with the ASTContext
First->CommonOrPrev = new Common;
}
return First->CommonOrPrev.get<Common*>();
}
//===----------------------------------------------------------------------===//
// ClassTemplateDecl Implementation
//===----------------------------------------------------------------------===//

View File

@ -1500,6 +1500,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
break;
// No code generation needed.
case Decl::Using:
case Decl::ClassTemplate:
case Decl::FunctionTemplate:
break;
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));

View File

@ -1036,14 +1036,22 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
FunctionTemplate->getDeclContext(),
*DeducedArgumentList));
if (!Specialization || Trap.hasErrorOccurred())
if (!Specialization)
return TDK_SubstitutionFailure;
// Turn the specialization into an actual function template specialization.
Specialization->setFunctionTemplateSpecialization(Context,
FunctionTemplate,
Info.take());
// If the template argument list is owned by the function template
// specialization, release it.
if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList)
Info.take();
// There may have been an error that did not prevent us from constructing a
// declaration. Mark the declaration invalid and return with a substitution
// failure.
if (Trap.hasErrorOccurred()) {
Specialization->setInvalidDecl(true);
return TDK_SubstitutionFailure;
}
return TDK_Success;
}

View File

@ -294,7 +294,24 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) {
}
Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
// FIXME: Look for existing specializations (explicit or otherwise).
// Check whether there is already a function template specialization for
// this declaration.
FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate();
void *InsertPos = 0;
if (FunctionTemplate) {
llvm::FoldingSetNodeID ID;
FunctionTemplateSpecializationInfo::Profile(ID,
TemplateArgs.getFlatArgumentList(),
TemplateArgs.flat_size());
FunctionTemplateSpecializationInfo *Info
= FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID,
InsertPos);
// If we already have a function template specialization, return it.
if (Info)
return Info->Function;
}
Sema::LocalInstantiationScope Scope(SemaRef);
@ -326,8 +343,13 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration,
/*FIXME:*/OverloadableAttrRequired);
// FIXME: link this to the function template from which it was instantiated.
if (FunctionTemplate) {
// Record this function template specialization.
Function->setFunctionTemplateSpecialization(SemaRef.Context,
FunctionTemplate,
&TemplateArgs,
InsertPos);
}
return Function;
}

View File

@ -0,0 +1,21 @@
// RUN: clang-cc -emit-llvm %s -o -
template<typename T, typename U>
T* next(T* ptr, const U& diff);
template<typename T, typename U>
T* next(T* ptr, const U& diff) {
return ptr + diff;
}
void test(int *iptr, float *fptr, int diff) {
iptr = next(iptr, diff);
fptr = next(fptr, diff);
}
template<typename T, typename U>
T* next(T* ptr, const U& diff);
void test2(int *iptr, double *dptr, int diff) {
iptr = next(iptr, diff);
dptr = next(dptr, diff);
}