[cfe-commits] r74454 - in /cfe/trunk: include/clang/AST/Decl.h include/clang/AST/DeclTemplate.h lib/AST/ASTContext.cpp lib/AST/Decl.cpp lib/AST/DeclTemplate.cpp lib/CodeGen/CodeGenModule.cpp lib/Sema/SemaTemplateDeduction.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/CodeGenCXX/function-template-specialization.cpp
Douglas Gregor
dgregor at apple.com
Mon Jun 29 13:59:41 PDT 2009
Author: dgregor
Date: Mon Jun 29 15:59:39 2009
New Revision: 74454
URL: http://llvm.org/viewvc/llvm-project?rev=74454&view=rev
Log:
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.
Added:
cfe/trunk/test/CodeGenCXX/function-template-specialization.cpp
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/include/clang/AST/DeclTemplate.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/Decl.cpp
cfe/trunk/lib/AST/DeclTemplate.cpp
cfe/trunk/lib/CodeGen/CodeGenModule.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Mon Jun 29 15:59:39 2009
@@ -809,9 +809,7 @@
return PreviousDeclaration;
}
- void setPreviousDeclaration(FunctionDecl * PrevDecl) {
- PreviousDeclaration = PrevDecl;
- }
+ void setPreviousDeclaration(FunctionDecl * PrevDecl);
unsigned getBuiltinID(ASTContext &Context) const;
@@ -961,7 +959,8 @@
/// 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) {
Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Mon Jun 29 15:59:39 2009
@@ -100,671 +100,723 @@
}
};
-//===----------------------------------------------------------------------===//
-// 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) { }
+/// \brief Represents a template argument within a class template
+/// specialization.
+class TemplateArgument {
+ union {
+ uintptr_t TypeOrValue;
+ struct {
+ char Value[sizeof(llvm::APSInt)];
+ void *Type;
+ } Integer;
+ struct {
+ TemplateArgument *Args;
+ unsigned NumArgs;
+ bool CopyArgs;
+ } Args;
+ };
+
+ /// \brief Location of the beginning of this template argument.
+ SourceLocation StartLoc;
+
public:
- ~TemplateDecl();
-
- /// Get the list of template parameters
- TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
+ /// \brief The type of template argument we're storing.
+ enum ArgKind {
+ Null = 0,
+ /// The template argument is a type. Its value is stored in the
+ /// TypeOrValue field.
+ Type = 1,
+ /// The template argument is a declaration
+ Declaration = 2,
+ /// The template argument is an integral value stored in an llvm::APSInt.
+ Integral = 3,
+ /// The template argument is a value- or type-dependent expression
+ /// stored in an Expr*.
+ Expression = 4,
+
+ /// The template argument is actually a parameter pack. Arguments are stored
+ /// in the Args struct.
+ Pack = 5
+ } Kind;
+
+ /// \brief Construct an empty, invalid template argument.
+ TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
+
+ /// \brief Construct a template type argument.
+ TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
+ TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
+ StartLoc = Loc;
}
-
- /// 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;
+
+ /// \brief Construct a template argument that refers to a
+ /// declaration, which is either an external declaration or a
+ /// template declaration.
+ TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
+ // FIXME: Need to be sure we have the "canonical" declaration!
+ TypeOrValue = reinterpret_cast<uintptr_t>(D);
+ StartLoc = Loc;
}
- 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 Construct an integral constant template argument.
+ TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
+ QualType Type)
+ : Kind(Integral) {
+ new (Integer.Value) llvm::APSInt(Value);
+ Integer.Type = Type.getAsOpaquePtr();
+ 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 (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else if (Kind == Pack) {
+ Args.NumArgs = Other.Args.NumArgs;
+ Args.Args = new TemplateArgument[Args.NumArgs];
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I] = Other.Args.Args[I];
+ }
+ else
+ TypeOrValue = Other.TypeOrValue;
+ StartLoc = Other.StartLoc;
+ }
+
+ TemplateArgument& operator=(const TemplateArgument& Other) {
+ // FIXME: Does not provide the strong guarantee for exception
+ // safety.
+ using llvm::APSInt;
- /// \brief The class template partial specializations for this class
- /// template.
- llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>
- PartialSpecializations;
+ // FIXME: Handle Packs
+ assert(Kind != Pack && "FIXME: Handle packs");
+ assert(Other.Kind != Pack && "FIXME: Handle packs");
- /// \brief The injected-class-name type for this class template.
- QualType InjectedClassNameType;
+ if (Kind == Other.Kind && Kind == Integral) {
+ // Copy integral values.
+ *this->getAsIntegral() = *Other.getAsIntegral();
+ Integer.Type = Other.Integer.Type;
+ } else {
+ // Destroy the current integral value, if that's what we're holding.
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+
+ Kind = Other.Kind;
+
+ if (Other.Kind == Integral) {
+ new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
+ Integer.Type = Other.Integer.Type;
+ } else
+ TypeOrValue = Other.TypeOrValue;
+ }
+ StartLoc = Other.StartLoc;
+
+ return *this;
+ }
+
+ ~TemplateArgument() {
+ using llvm::APSInt;
+
+ if (Kind == Integral)
+ getAsIntegral()->~APSInt();
+ else if (Kind == Pack && Args.CopyArgs)
+ delete[] Args.Args;
+ }
+
+ /// \brief Return the kind of stored template argument.
+ ArgKind getKind() const { return Kind; }
+
+ /// \brief Determine whether this template argument has no value.
+ bool isNull() const { return Kind == Null; }
+
+ /// \brief Retrieve the template argument as a type.
+ QualType getAsType() const {
+ if (Kind != Type)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(
+ reinterpret_cast<void*>(TypeOrValue));
+ }
+
+ /// \brief Retrieve the template argument as a declaration.
+ Decl *getAsDecl() const {
+ if (Kind != Declaration)
+ return 0;
+ return reinterpret_cast<Decl *>(TypeOrValue);
+ }
+
+ /// \brief Retrieve the template argument as an integral value.
+ llvm::APSInt *getAsIntegral() {
+ if (Kind != Integral)
+ return 0;
+ return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
+ }
+
+ const llvm::APSInt *getAsIntegral() const {
+ return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ }
+
+ /// \brief Retrieve the type of the integral value.
+ QualType getIntegralType() const {
+ if (Kind != Integral)
+ return QualType();
+
+ return QualType::getFromOpaquePtr(Integer.Type);
+ }
+
+ void setIntegralType(QualType T) {
+ assert(Kind == Integral &&
+ "Cannot set the integral type of a non-integral template argument");
+ Integer.Type = T.getAsOpaquePtr();
};
- 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);
+ /// \brief Retrieve the template argument as an expression.
+ Expr *getAsExpr() const {
+ if (Kind != Expression)
+ return 0;
+
+ return reinterpret_cast<Expr *>(TypeOrValue);
}
-
- /// 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();
+ /// \brief Iterator that traverses the elements of a template argument pack.
+ typedef const TemplateArgument * pack_iterator;
+
+ /// \brief Iterator referencing the first argument of a template argument
+ /// pack.
+ pack_iterator pack_begin() const {
+ assert(Kind == Pack);
+ return Args.Args;
+ }
+
+ /// \brief Iterator referencing one past the last argument of a template
+ /// argument pack.
+ pack_iterator pack_end() const {
+ assert(Kind == Pack);
+ return Args.Args + Args.NumArgs;
}
-
-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 The number of template arguments in the given template argument
+ /// pack.
+ unsigned pack_size() const {
+ assert(Kind == Pack);
+ return Args.NumArgs;
}
-
- /// \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;
+
+ /// \brief Retrieve the location where the template argument starts.
+ SourceLocation getLocation() const { return StartLoc; }
+
+ /// \brief Construct a template argument pack.
+ void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+
+ /// \brief Used to insert TemplateArguments into FoldingSets.
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(Kind);
+ switch (Kind) {
+ case Null:
+ break;
+
+ case Type:
+ getAsType().Profile(ID);
+ break;
+
+ case Declaration:
+ ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
+ break;
+
+ case Integral:
+ getAsIntegral()->Profile(ID);
+ getIntegralType().Profile(ID);
+ break;
+
+ case Expression:
+ // FIXME: We need a canonical representation of expressions.
+ ID.AddPointer(getAsExpr());
+ break;
+
+ case Pack:
+ ID.AddInteger(Args.NumArgs);
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I].Profile(ID);
+ }
}
- 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)
- { }
-
+/// \brief A helper class for making template argument lists.
+class TemplateArgumentListBuilder {
+ TemplateArgument *StructuredArgs;
+ unsigned MaxStructuredArgs;
+ unsigned NumStructuredArgs;
+
+ TemplateArgument *FlatArgs;
+ unsigned MaxFlatArgs;
+ unsigned NumFlatArgs;
+
+ bool AddingToPack;
+ unsigned PackBeginIndex;
+
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;
+ TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
+ unsigned NumTemplateArgs)
+ : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
+ NumStructuredArgs(0), FlatArgs(0),
+ MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
+ AddingToPack(false), PackBeginIndex(0) { }
+
+ void Append(const TemplateArgument& Arg);
+ void BeginPack();
+ void EndPack();
+
+ void ReleaseArgs();
+
+ unsigned flatSize() const {
+ return NumFlatArgs;
+ }
+ const TemplateArgument *getFlatArguments() const {
+ return FlatArgs;
+ }
+
+ unsigned structuredSize() const {
+ // If we don't have any structured args, just reuse the flat size.
+ if (!StructuredArgs)
+ return flatSize();
- /// \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;
+ return NumStructuredArgs;
}
-
- // Implement isa/cast/dyncast/etc.
- static bool classof(const Decl *D) {
- return D->getKind() == NonTypeTemplateParm;
+ const TemplateArgument *getStructuredArguments() const {
+ // If we don't have any structured args, just reuse the flat args.
+ if (!StructuredArgs)
+ return getFlatArguments();
+
+ return StructuredArgs;
}
- 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)
- { }
-
+/// \brief A template argument list.
+///
+/// FIXME: In the future, this class will be extended to support
+/// variadic templates and member templates, which will make some of
+/// the function names below make more sense.
+class TemplateArgumentList {
+ /// \brief The template argument list.
+ ///
+ /// The integer value will be non-zero to indicate that this
+ /// template argument list does not own the pointer.
+ llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
+
+ /// \brief The number of template arguments in this template
+ /// argument list.
+ unsigned NumFlatArguments;
+
+ llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
+ unsigned NumStructuredArguments;
+
public:
- static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
- SourceLocation L, unsigned D,
- unsigned P, IdentifierInfo *Id,
- TemplateParameterList *Params);
+ TemplateArgumentList(ASTContext &Context,
+ TemplateArgumentListBuilder &Builder,
+ bool TakeArgs);
+
+ ~TemplateArgumentList();
+
+ /// \brief Retrieve the template argument at a given index.
+ const TemplateArgument &get(unsigned Idx) const {
+ assert(Idx < NumFlatArguments && "Invalid template argument index");
+ return getFlatArgumentList()[Idx];
+ }
+
+ /// \brief Retrieve the template argument at a given index.
+ const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+
+ /// \brief Retrieve the number of template arguments in this
+ /// template argument list.
+ unsigned size() const { return NumFlatArguments; }
+
+ /// \brief Retrieve the number of template arguments in the
+ /// flattened template argument list.
+ unsigned flat_size() const { return NumFlatArguments; }
+
+ /// \brief Retrieve the flattened template argument list.
+ const TemplateArgument *getFlatArgumentList() const {
+ return FlatArguments.getPointer();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Kinds of Templates
+//===----------------------------------------------------------------------===//
- using TemplateParmPosition::getDepth;
- using TemplateParmPosition::getPosition;
- using TemplateParmPosition::getIndex;
-
- /// \brief Determine whether this template parameter has a default
- /// argument.
- bool hasDefaultArgument() const { return DefaultArgument; }
+/// 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)
+ { }
- /// \brief Retrieve the default argument, if any.
- Expr *getDefaultArgument() const { return DefaultArgument; }
+ // 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)
+ { }
- /// \brief Retrieve the location of the default argument, if any.
- SourceLocation getDefaultArgumentLoc() const;
+ // 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();
- /// \brief Set the default argument for this template parameter.
- void setDefaultArgument(Expr *DefArg) {
- DefaultArgument = DefArg;
+ /// 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() == TemplateTemplateParm;
+ 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; }
-};
-/// \brief Represents a template argument within a class template
-/// specialization.
-class TemplateArgument {
- union {
- uintptr_t TypeOrValue;
- struct {
- char Value[sizeof(llvm::APSInt)];
- void *Type;
- } Integer;
- struct {
- TemplateArgument *Args;
- unsigned NumArgs;
- bool CopyArgs;
- } Args;
+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 Location of the beginning of this template argument.
- SourceLocation StartLoc;
-
+
+ /// \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:
- /// \brief The type of template argument we're storing.
- enum ArgKind {
- Null = 0,
- /// The template argument is a type. Its value is stored in the
- /// TypeOrValue field.
- Type = 1,
- /// The template argument is a declaration
- Declaration = 2,
- /// The template argument is an integral value stored in an llvm::APSInt.
- Integral = 3,
- /// The template argument is a value- or type-dependent expression
- /// stored in an Expr*.
- Expression = 4,
-
- /// The template argument is actually a parameter pack. Arguments are stored
- /// in the Args struct.
- Pack = 5
- } Kind;
-
- /// \brief Construct an empty, invalid template argument.
- TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { }
-
- /// \brief Construct a template type argument.
- TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) {
- TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr());
- StartLoc = Loc;
+ void Destroy(ASTContext &C);
+
+ /// Get the underlying function declaration of the template.
+ FunctionDecl *getTemplatedDecl() const {
+ return static_cast<FunctionDecl*>(TemplatedDecl);
}
- /// \brief Construct a template argument that refers to a
- /// declaration, which is either an external declaration or a
- /// template declaration.
- TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) {
- // FIXME: Need to be sure we have the "canonical" declaration!
- TypeOrValue = reinterpret_cast<uintptr_t>(D);
- StartLoc = Loc;
+ /// \brief Retrieve the set of function template specializations of this
+ /// function template.
+ llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
+ return getCommonPtr()->Specializations;
}
-
- /// \brief Construct an integral constant template argument.
- TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value,
- QualType Type)
- : Kind(Integral) {
- new (Integer.Value) llvm::APSInt(Value);
- Integer.Type = Type.getAsOpaquePtr();
- StartLoc = Loc;
+
+ /// \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 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 (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else if (Kind == Pack) {
- Args.NumArgs = Other.Args.NumArgs;
- Args.Args = new TemplateArgument[Args.NumArgs];
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I] = Other.Args.Args[I];
- }
- else
- TypeOrValue = Other.TypeOrValue;
- StartLoc = Other.StartLoc;
+ /// \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);
- TemplateArgument& operator=(const TemplateArgument& Other) {
- // FIXME: Does not provide the strong guarantee for exception
- // safety.
- using llvm::APSInt;
-
- // FIXME: Handle Packs
- assert(Kind != Pack && "FIXME: Handle packs");
- assert(Other.Kind != Pack && "FIXME: Handle packs");
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D)
+ { return D->getKind() == FunctionTemplate; }
+ static bool classof(const FunctionTemplateDecl *D)
+ { return true; }
+};
- if (Kind == Other.Kind && Kind == Integral) {
- // Copy integral values.
- *this->getAsIntegral() = *Other.getAsIntegral();
- Integer.Type = Other.Integer.Type;
- } else {
- // Destroy the current integral value, if that's what we're holding.
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
-
- Kind = Other.Kind;
-
- if (Other.Kind == Integral) {
- new (Integer.Value) llvm::APSInt(*Other.getAsIntegral());
- Integer.Type = Other.Integer.Type;
- } else
- TypeOrValue = Other.TypeOrValue;
- }
- StartLoc = Other.StartLoc;
+//===----------------------------------------------------------------------===//
+// Kinds of Template Parameters
+//===----------------------------------------------------------------------===//
- return *this;
- }
+/// 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"); */ }
- ~TemplateArgument() {
- using llvm::APSInt;
+ TemplateParmPosition(unsigned D, unsigned P)
+ : Depth(D), Position(P)
+ { }
- if (Kind == Integral)
- getAsIntegral()->~APSInt();
- else if (Kind == Pack && Args.CopyArgs)
- delete[] Args.Args;
- }
+ // FIXME: These probably don't need to be ints. int:5 for depth, int:8 for
+ // position? Maybe?
+ unsigned Depth;
+ unsigned Position;
- /// \brief Return the kind of stored template argument.
- ArgKind getKind() const { return Kind; }
+public:
+ /// Get the nesting depth of the template parameter.
+ unsigned getDepth() const { return Depth; }
- /// \brief Determine whether this template argument has no value.
- bool isNull() const { return Kind == Null; }
+ /// Get the position of the template parameter within its parameter list.
+ unsigned getPosition() const { return Position; }
- /// \brief Retrieve the template argument as a type.
- QualType getAsType() const {
- if (Kind != Type)
- return QualType();
+ /// Get the index of the template parameter within its parameter list.
+ unsigned getIndex() const { return Position; }
+};
- return QualType::getFromOpaquePtr(
- reinterpret_cast<void*>(TypeOrValue));
- }
+/// 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 Retrieve the template argument as a declaration.
- Decl *getAsDecl() const {
- if (Kind != Declaration)
- return 0;
- return reinterpret_cast<Decl *>(TypeOrValue);
- }
+ /// \brief Whether this template type parameter inherited its
+ /// default argument.
+ bool InheritedDefault : 1;
- /// \brief Retrieve the template argument as an integral value.
- llvm::APSInt *getAsIntegral() {
- if (Kind != Integral)
- return 0;
- return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]);
- }
+ /// \brief Whether this is a parameter pack.
+ bool ParameterPack : 1;
+
+ /// \brief The location of the default argument, if any.
+ SourceLocation DefaultArgumentLoc;
- const llvm::APSInt *getAsIntegral() const {
- return const_cast<TemplateArgument*>(this)->getAsIntegral();
+ /// \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();
}
- /// \brief Retrieve the type of the integral value.
- QualType getIntegralType() const {
- if (Kind != Integral)
- return QualType();
+public:
+ static TemplateTypeParmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D, unsigned P,
+ IdentifierInfo *Id, bool Typename,
+ bool ParameterPack);
- return QualType::getFromOpaquePtr(Integer.Type);
- }
+ /// \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; }
- void setIntegralType(QualType T) {
- assert(Kind == Integral &&
- "Cannot set the integral type of a non-integral template argument");
- Integer.Type = T.getAsOpaquePtr();
- };
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return !DefaultArgument.isNull(); }
- /// \brief Retrieve the template argument as an expression.
- Expr *getAsExpr() const {
- if (Kind != Expression)
- return 0;
+ /// \brief Retrieve the default argument, if any.
+ QualType getDefaultArgument() const { return DefaultArgument; }
- return reinterpret_cast<Expr *>(TypeOrValue);
- }
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const { return DefaultArgumentLoc; }
- /// \brief Iterator that traverses the elements of a template argument pack.
- typedef const TemplateArgument * pack_iterator;
-
- /// \brief Iterator referencing the first argument of a template argument
- /// pack.
- pack_iterator pack_begin() const {
- assert(Kind == Pack);
- return Args.Args;
- }
+ /// \brief Determines whether the default argument was inherited
+ /// from a previous declaration of this template.
+ bool defaultArgumentWasInherited() const { return InheritedDefault; }
- /// \brief Iterator referencing one past the last argument of a template
- /// argument pack.
- pack_iterator pack_end() const {
- assert(Kind == Pack);
- return Args.Args + Args.NumArgs;
- }
-
- /// \brief The number of template arguments in the given template argument
- /// pack.
- unsigned pack_size() const {
- assert(Kind == Pack);
- return Args.NumArgs;
+ /// \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 Retrieve the location where the template argument starts.
- SourceLocation getLocation() const { return StartLoc; }
- /// \brief Construct a template argument pack.
- void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+ /// \brief Returns whether this is a parameter pack.
+ bool isParameterPack() const { return ParameterPack; }
- /// \brief Used to insert TemplateArguments into FoldingSets.
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(Kind);
- switch (Kind) {
- case Null:
- break;
-
- case Type:
- getAsType().Profile(ID);
- break;
-
- case Declaration:
- ID.AddPointer(getAsDecl()); // FIXME: Must be canonical!
- break;
-
- case Integral:
- getAsIntegral()->Profile(ID);
- getIntegralType().Profile(ID);
- break;
-
- case Expression:
- // FIXME: We need a canonical representation of expressions.
- ID.AddPointer(getAsExpr());
- break;
-
- case Pack:
- ID.AddInteger(Args.NumArgs);
- for (unsigned I = 0; I != Args.NumArgs; ++I)
- Args.Args[I].Profile(ID);
- }
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == TemplateTypeParm;
}
+ static bool classof(const TemplateTypeParmDecl *D) { return true; }
};
-/// \brief A helper class for making template argument lists.
-class TemplateArgumentListBuilder {
- TemplateArgument *StructuredArgs;
- unsigned MaxStructuredArgs;
- unsigned NumStructuredArgs;
-
- TemplateArgument *FlatArgs;
- unsigned MaxFlatArgs;
- unsigned NumFlatArgs;
-
- bool AddingToPack;
- unsigned PackBeginIndex;
-
+/// 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:
- TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
- unsigned NumTemplateArgs)
- : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
- NumStructuredArgs(0), FlatArgs(0),
- MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
- AddingToPack(false), PackBeginIndex(0) { }
-
- void Append(const TemplateArgument& Arg);
- void BeginPack();
- void EndPack();
+ static NonTypeTemplateParmDecl *
+ Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id, QualType T,
+ SourceLocation TypeSpecStartLoc = SourceLocation());
- void ReleaseArgs();
-
- unsigned flatSize() const {
- return NumFlatArgs;
- }
- const TemplateArgument *getFlatArguments() const {
- return FlatArgs;
- }
-
- unsigned structuredSize() const {
- // If we don't have any structured args, just reuse the flat size.
- if (!StructuredArgs)
- return flatSize();
+ using TemplateParmPosition::getDepth;
+ using TemplateParmPosition::getPosition;
+ using TemplateParmPosition::getIndex;
+
+ /// \brief Determine whether this template parameter has a default
+ /// argument.
+ bool hasDefaultArgument() const { return DefaultArgument; }
- return NumStructuredArgs;
+ /// \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;
}
- const TemplateArgument *getStructuredArguments() const {
- // If we don't have any structured args, just reuse the flat args.
- if (!StructuredArgs)
- return getFlatArguments();
-
- return StructuredArgs;
+
+ // Implement isa/cast/dyncast/etc.
+ static bool classof(const Decl *D) {
+ return D->getKind() == NonTypeTemplateParm;
}
+ static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
};
-/// \brief A template argument list.
-///
-/// FIXME: In the future, this class will be extended to support
-/// variadic templates and member templates, which will make some of
-/// the function names below make more sense.
-class TemplateArgumentList {
- /// \brief The template argument list.
- ///
- /// The integer value will be non-zero to indicate that this
- /// template argument list does not own the pointer.
- llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
+/// 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 number of template arguments in this template
- /// argument list.
- unsigned NumFlatArguments;
+ /// \brief The default template argument, if any.
+ Expr *DefaultArgument;
- llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
- unsigned NumStructuredArguments;
-
-public:
- TemplateArgumentList(ASTContext &Context,
- TemplateArgumentListBuilder &Builder,
- bool TakeArgs);
+ TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
+ unsigned D, unsigned P,
+ IdentifierInfo *Id, TemplateParameterList *Params)
+ : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
+ TemplateParmPosition(D, P), DefaultArgument(0)
+ { }
- ~TemplateArgumentList();
+public:
+ static TemplateTemplateParmDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, unsigned D,
+ unsigned P, IdentifierInfo *Id,
+ TemplateParameterList *Params);
- /// \brief Retrieve the template argument at a given index.
- const TemplateArgument &get(unsigned Idx) const {
- assert(Idx < NumFlatArguments && "Invalid template argument index");
- return getFlatArgumentList()[Idx];
- }
+ 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 template argument at a given index.
- const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); }
+ /// \brief Retrieve the default argument, if any.
+ Expr *getDefaultArgument() const { return DefaultArgument; }
- /// \brief Retrieve the number of template arguments in this
- /// template argument list.
- unsigned size() const { return NumFlatArguments; }
+ /// \brief Retrieve the location of the default argument, if any.
+ SourceLocation getDefaultArgumentLoc() const;
- /// \brief Retrieve the number of template arguments in the
- /// flattened template argument list.
- unsigned flat_size() const { return NumFlatArguments; }
+ /// \brief Set the default argument for this template parameter.
+ void setDefaultArgument(Expr *DefArg) {
+ DefaultArgument = DefArg;
+ }
- /// \brief Retrieve the flattened template argument list.
- const TemplateArgument *getFlatArgumentList() const {
- return FlatArguments.getPointer();
+ // 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
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Mon Jun 29 15:59:39 2009
@@ -1806,6 +1806,12 @@
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();
Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Jun 29 15:59:39 2009
@@ -372,11 +372,6 @@
C.Deallocate(ParamInfo);
- if (FunctionTemplateSpecializationInfo *Info
- = TemplateOrSpecialization
- .dyn_cast<FunctionTemplateSpecializationInfo*>())
- C.Deallocate(Info);
-
Decl::Destroy(C);
}
@@ -564,6 +559,18 @@
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 @@
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);
}
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Mon Jun 29 15:59:39 2009
@@ -81,11 +81,36 @@
DeclContext *DC,
SourceLocation L,
DeclarationName Name,
- TemplateParameterList *Params,
+ TemplateParameterList *Params,
NamedDecl *Decl) {
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
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Mon Jun 29 15:59:39 2009
@@ -1500,6 +1500,8 @@
break;
// No code generation needed.
case Decl::Using:
+ case Decl::ClassTemplate:
+ case Decl::FunctionTemplate:
break;
case Decl::CXXConstructor:
EmitCXXConstructors(cast<CXXConstructorDecl>(D));
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Mon Jun 29 15:59:39 2009
@@ -1036,14 +1036,22 @@
InstantiateDecl(FunctionTemplate->getTemplatedDecl(),
FunctionTemplate->getDeclContext(),
*DeducedArgumentList));
+ if (!Specialization)
+ return TDK_SubstitutionFailure;
- if (!Specialization || Trap.hasErrorOccurred())
+ // 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;
-
- // Turn the specialization into an actual function template specialization.
- Specialization->setFunctionTemplateSpecialization(Context,
- FunctionTemplate,
- Info.take());
+ }
+
return TDK_Success;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=74454&r1=74453&r2=74454&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Mon Jun 29 15:59:39 2009
@@ -294,7 +294,24 @@
}
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);
@@ -325,10 +342,15 @@
NamedDecl *PrevDecl = 0;
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;
}
Added: cfe/trunk/test/CodeGenCXX/function-template-specialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/function-template-specialization.cpp?rev=74454&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/function-template-specialization.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/function-template-specialization.cpp Mon Jun 29 15:59:39 2009
@@ -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);
+}
\ No newline at end of file
More information about the cfe-commits
mailing list