1434 lines
53 KiB
C++
1434 lines
53 KiB
C++
//===-- DeclTemplate.h - Classes for representing C++ templates -*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the C++ template declaration subclasses.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_AST_DECLTEMPLATE_H
|
|
#define LLVM_CLANG_AST_DECLTEMPLATE_H
|
|
|
|
#include "clang/AST/DeclCXX.h"
|
|
#include "clang/AST/TemplateBase.h"
|
|
#include "llvm/ADT/PointerUnion.h"
|
|
#include <limits>
|
|
|
|
namespace clang {
|
|
|
|
class TemplateParameterList;
|
|
class TemplateDecl;
|
|
class FunctionTemplateDecl;
|
|
class ClassTemplateDecl;
|
|
class ClassTemplatePartialSpecializationDecl;
|
|
class TemplateTypeParmDecl;
|
|
class NonTypeTemplateParmDecl;
|
|
class TemplateTemplateParmDecl;
|
|
|
|
/// \brief Stores a template parameter of any kind.
|
|
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
|
|
TemplateTemplateParmDecl*> TemplateParameter;
|
|
|
|
/// TemplateParameterList - Stores a list of template parameters for a
|
|
/// TemplateDecl and its derived classes.
|
|
class TemplateParameterList {
|
|
/// The location of the 'template' keyword.
|
|
SourceLocation TemplateLoc;
|
|
|
|
/// The locations of the '<' and '>' angle brackets.
|
|
SourceLocation LAngleLoc, RAngleLoc;
|
|
|
|
/// The number of template parameters in this template
|
|
/// parameter list.
|
|
unsigned NumParams;
|
|
|
|
TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc,
|
|
NamedDecl **Params, unsigned NumParams,
|
|
SourceLocation RAngleLoc);
|
|
|
|
public:
|
|
static TemplateParameterList *Create(ASTContext &C,
|
|
SourceLocation TemplateLoc,
|
|
SourceLocation LAngleLoc,
|
|
NamedDecl **Params,
|
|
unsigned NumParams,
|
|
SourceLocation RAngleLoc);
|
|
|
|
/// iterator - Iterates through the template parameters in this list.
|
|
typedef NamedDecl** iterator;
|
|
|
|
/// const_iterator - Iterates through the template parameters in this list.
|
|
typedef NamedDecl* const* const_iterator;
|
|
|
|
iterator begin() { return reinterpret_cast<NamedDecl **>(this + 1); }
|
|
const_iterator begin() const {
|
|
return reinterpret_cast<NamedDecl * const *>(this + 1);
|
|
}
|
|
iterator end() { return begin() + NumParams; }
|
|
const_iterator end() const { return begin() + NumParams; }
|
|
|
|
unsigned size() const { return NumParams; }
|
|
|
|
NamedDecl* getParam(unsigned Idx) {
|
|
assert(Idx < size() && "Template parameter index out-of-range");
|
|
return begin()[Idx];
|
|
}
|
|
|
|
const NamedDecl* getParam(unsigned Idx) const {
|
|
assert(Idx < size() && "Template parameter index out-of-range");
|
|
return begin()[Idx];
|
|
}
|
|
|
|
/// \btief Returns the minimum number of arguments needed to form a
|
|
/// template specialization. This may be fewer than the number of
|
|
/// template parameters, if some of the parameters have default
|
|
/// arguments or if there is a parameter pack.
|
|
unsigned getMinRequiredArguments() const;
|
|
|
|
/// \brief Get the depth of this template parameter list in the set of
|
|
/// template parameter lists.
|
|
///
|
|
/// The first template parameter list in a declaration will have depth 0,
|
|
/// the second template parameter list will have depth 1, etc.
|
|
unsigned getDepth() const;
|
|
|
|
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
|
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
|
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
|
|
|
SourceRange getSourceRange() const {
|
|
return SourceRange(TemplateLoc, RAngleLoc);
|
|
}
|
|
};
|
|
|
|
/// \brief A helper class for making template argument lists.
|
|
class TemplateArgumentListBuilder {
|
|
TemplateArgument *StructuredArgs;
|
|
unsigned MaxStructuredArgs;
|
|
unsigned NumStructuredArgs;
|
|
|
|
llvm::SmallVector<TemplateArgument, 4> FlatArgs;
|
|
unsigned MaxFlatArgs;
|
|
unsigned NumFlatArgs;
|
|
|
|
bool AddingToPack;
|
|
unsigned PackBeginIndex;
|
|
|
|
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();
|
|
|
|
unsigned flatSize() const { return FlatArgs.size(); }
|
|
const TemplateArgument *getFlatArguments() const { return FlatArgs.data(); }
|
|
|
|
unsigned structuredSize() const {
|
|
// If we don't have any structured args, just reuse the flat size.
|
|
if (!StructuredArgs)
|
|
return flatSize();
|
|
|
|
return NumStructuredArgs;
|
|
}
|
|
const TemplateArgument *getStructuredArguments() const {
|
|
// If we don't have any structured args, just reuse the flat args.
|
|
if (!StructuredArgs)
|
|
return getFlatArguments();
|
|
|
|
return StructuredArgs;
|
|
}
|
|
};
|
|
|
|
/// \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 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;
|
|
|
|
TemplateArgumentList(const TemplateArgumentList &Other); // DO NOT IMPL
|
|
void operator=(const TemplateArgumentList &Other); // DO NOT IMPL
|
|
public:
|
|
/// TemplateArgumentList - If this constructor is passed "true" for 'TakeArgs'
|
|
/// it copies them into a locally new[]'d array. If passed "false", then it
|
|
/// just references the array passed in. This is only safe if the builder
|
|
/// outlives it, but saves a copy.
|
|
TemplateArgumentList(ASTContext &Context,
|
|
TemplateArgumentListBuilder &Builder,
|
|
bool TakeArgs);
|
|
|
|
/// Produces a shallow copy of the given template argument list. This
|
|
/// assumes that the input argument list outlives it. This takes the list as
|
|
/// a pointer to avoid looking like a copy constructor, since this really
|
|
/// really isn't safe to use that way.
|
|
explicit TemplateArgumentList(const TemplateArgumentList *Other);
|
|
|
|
/// Used to release the memory associated with a TemplateArgumentList
|
|
/// object. FIXME: This is currently not called anywhere, but the
|
|
/// memory will still be freed when using a BumpPtrAllocator.
|
|
void Destroy(ASTContext &C);
|
|
|
|
~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
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// 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 classofKind(D->getKind()); }
|
|
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; }
|
|
static bool classofKind(Kind K) {
|
|
return K >= TemplateFirst && K <= TemplateLast;
|
|
}
|
|
|
|
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.
|
|
///
|
|
/// The two bits are contain the top 4 values of TemplateSpecializationKind.
|
|
llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template;
|
|
|
|
/// \brief The template arguments used to produce the function template
|
|
/// specialization from the function template.
|
|
const TemplateArgumentList *TemplateArguments;
|
|
|
|
/// \brief The template arguments as written in the sources, if provided.
|
|
const TemplateArgumentListInfo *TemplateArgumentsAsWritten;
|
|
|
|
/// \brief The point at which this function template specialization was
|
|
/// first instantiated.
|
|
SourceLocation PointOfInstantiation;
|
|
|
|
/// \brief Retrieve the template from which this function was specialized.
|
|
FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); }
|
|
|
|
/// \brief Determine what kind of template specialization this is.
|
|
TemplateSpecializationKind getTemplateSpecializationKind() const {
|
|
return (TemplateSpecializationKind)(Template.getInt() + 1);
|
|
}
|
|
|
|
/// \brief Set the template specialization kind.
|
|
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
|
assert(TSK != TSK_Undeclared &&
|
|
"Cannot encode TSK_Undeclared for a function template specialization");
|
|
Template.setInt(TSK - 1);
|
|
}
|
|
|
|
/// \brief Retrieve the first point of instantiation of this function
|
|
/// template specialization.
|
|
///
|
|
/// The point of instantiation may be an invalid source location if this
|
|
/// function has yet to be instantiated.
|
|
SourceLocation getPointOfInstantiation() const {
|
|
return PointOfInstantiation;
|
|
}
|
|
|
|
/// \brief Set the (first) point of instantiation of this function template
|
|
/// specialization.
|
|
void setPointOfInstantiation(SourceLocation POI) {
|
|
PointOfInstantiation = POI;
|
|
}
|
|
|
|
void Profile(llvm::FoldingSetNodeID &ID) {
|
|
Profile(ID, TemplateArguments->getFlatArgumentList(),
|
|
TemplateArguments->flat_size(),
|
|
Function->getASTContext());
|
|
}
|
|
|
|
static void
|
|
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
|
|
unsigned NumTemplateArgs, ASTContext &Context) {
|
|
ID.AddInteger(NumTemplateArgs);
|
|
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
|
|
TemplateArgs[Arg].Profile(ID, Context);
|
|
}
|
|
};
|
|
|
|
/// \brief Provides information a specialization of a member of a class
|
|
/// template, which may be a member function, static data member, or
|
|
/// member class.
|
|
class MemberSpecializationInfo {
|
|
// The member declaration from which this member was instantiated, and the
|
|
// manner in which the instantiation occurred (in the lower two bits).
|
|
llvm::PointerIntPair<NamedDecl *, 2> MemberAndTSK;
|
|
|
|
// The point at which this member was first instantiated.
|
|
SourceLocation PointOfInstantiation;
|
|
|
|
public:
|
|
explicit
|
|
MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK)
|
|
: MemberAndTSK(IF, TSK - 1), PointOfInstantiation() {
|
|
assert(TSK != TSK_Undeclared &&
|
|
"Cannot encode undeclared template specializations for members");
|
|
}
|
|
|
|
/// \brief Retrieve the member declaration from which this member was
|
|
/// instantiated.
|
|
NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); }
|
|
|
|
/// \brief Determine what kind of template specialization this is.
|
|
TemplateSpecializationKind getTemplateSpecializationKind() const {
|
|
return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1);
|
|
}
|
|
|
|
/// \brief Set the template specialization kind.
|
|
void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
|
|
assert(TSK != TSK_Undeclared &&
|
|
"Cannot encode undeclared template specializations for members");
|
|
MemberAndTSK.setInt(TSK - 1);
|
|
}
|
|
|
|
/// \brief Retrieve the first point of instantiation of this member.
|
|
/// If the point of instantiation is an invalid location, then this member
|
|
/// has not yet been instantiated.
|
|
SourceLocation getPointOfInstantiation() const {
|
|
return PointOfInstantiation;
|
|
}
|
|
|
|
/// \brief Set the first point of instantiation.
|
|
void setPointOfInstantiation(SourceLocation POI) {
|
|
PointOfInstantiation = POI;
|
|
}
|
|
};
|
|
|
|
/// \brief Provides information about a dependent function-template
|
|
/// specialization declaration. Since explicit function template
|
|
/// specialization and instantiation declarations can only appear in
|
|
/// namespace scope, and you can only specialize a member of a
|
|
/// fully-specialized class, the only way to get one of these is in
|
|
/// a friend declaration like the following:
|
|
///
|
|
/// template <class T> void foo(T);
|
|
/// template <class T> class A {
|
|
/// friend void foo<>(T);
|
|
/// };
|
|
class DependentFunctionTemplateSpecializationInfo {
|
|
union {
|
|
// Force sizeof to be a multiple of sizeof(void*) so that the
|
|
// trailing data is aligned.
|
|
void *Aligner;
|
|
|
|
struct {
|
|
/// The number of potential template candidates.
|
|
unsigned NumTemplates;
|
|
|
|
/// The number of template arguments.
|
|
unsigned NumArgs;
|
|
} d;
|
|
};
|
|
|
|
/// The locations of the left and right angle brackets.
|
|
SourceRange AngleLocs;
|
|
|
|
FunctionTemplateDecl * const *getTemplates() const {
|
|
return reinterpret_cast<FunctionTemplateDecl*const*>(this+1);
|
|
}
|
|
|
|
const TemplateArgumentLoc *getTemplateArgs() const {
|
|
return reinterpret_cast<const TemplateArgumentLoc*>(
|
|
&getTemplates()[getNumTemplates()]);
|
|
}
|
|
|
|
public:
|
|
DependentFunctionTemplateSpecializationInfo(
|
|
const UnresolvedSetImpl &Templates,
|
|
const TemplateArgumentListInfo &TemplateArgs);
|
|
|
|
/// \brief Returns the number of function templates that this might
|
|
/// be a specialization of.
|
|
unsigned getNumTemplates() const {
|
|
return d.NumTemplates;
|
|
}
|
|
|
|
/// \brief Returns the i'th template candidate.
|
|
FunctionTemplateDecl *getTemplate(unsigned I) const {
|
|
assert(I < getNumTemplates() && "template index out of range");
|
|
return getTemplates()[I];
|
|
}
|
|
|
|
/// \brief Returns the number of explicit template arguments that were given.
|
|
unsigned getNumTemplateArgs() const {
|
|
return d.NumArgs;
|
|
}
|
|
|
|
/// \brief Returns the nth template argument.
|
|
const TemplateArgumentLoc &getTemplateArg(unsigned I) const {
|
|
assert(I < getNumTemplateArgs() && "template arg index out of range");
|
|
return getTemplateArgs()[I];
|
|
}
|
|
|
|
SourceLocation getLAngleLoc() const {
|
|
return AngleLocs.getBegin();
|
|
}
|
|
|
|
SourceLocation getRAngleLoc() const {
|
|
return AngleLocs.getEnd();
|
|
}
|
|
};
|
|
|
|
/// Declaration of a template function.
|
|
class FunctionTemplateDecl : public TemplateDecl {
|
|
static void DeallocateCommon(void *Ptr);
|
|
|
|
protected:
|
|
/// \brief Data that is common to all of the declarations of a given
|
|
/// function template.
|
|
struct Common {
|
|
Common() : InstantiatedFromMember(0, false) { }
|
|
|
|
/// \brief The function template specializations for this function
|
|
/// template, including explicit specializations and instantiations.
|
|
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
|
|
|
|
/// \brief The member function template from which this was most
|
|
/// directly instantiated (or null).
|
|
///
|
|
/// The boolean value indicates whether this member function template
|
|
/// was explicitly specialized.
|
|
llvm::PointerIntPair<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
|
|
};
|
|
|
|
/// \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;
|
|
}
|
|
|
|
virtual FunctionTemplateDecl *getCanonicalDecl();
|
|
|
|
/// \brief Retrieve the member function template that this function template
|
|
/// was instantiated from.
|
|
///
|
|
/// This routine will return non-NULL for member function templates of
|
|
/// class templates. For example, given:
|
|
///
|
|
/// \code
|
|
/// template <typename T>
|
|
/// struct X {
|
|
/// template <typename U> void f();
|
|
/// };
|
|
/// \endcode
|
|
///
|
|
/// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
|
|
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
|
|
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
|
|
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
|
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
|
|
/// ClassTemplateDecl).
|
|
///
|
|
/// \returns NULL if this is not an instantiation of a member function
|
|
/// template.
|
|
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
|
|
return getCommonPtr()->InstantiatedFromMember.getPointer();
|
|
}
|
|
|
|
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
|
|
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
|
|
getCommonPtr()->InstantiatedFromMember.setPointer(FTD);
|
|
}
|
|
|
|
/// \brief Determines whether this template was a specialization of a
|
|
/// member template.
|
|
///
|
|
/// In the following example, the function template \c X<int>::f is a
|
|
/// member specialization.
|
|
///
|
|
/// \code
|
|
/// template<typename T>
|
|
/// struct X {
|
|
/// template<typename U> void f(T, U);
|
|
/// };
|
|
///
|
|
/// template<> template<typename T>
|
|
/// void X<int>::f(int, T);
|
|
/// \endcode
|
|
bool isMemberSpecialization() {
|
|
return getCommonPtr()->InstantiatedFromMember.getInt();
|
|
}
|
|
|
|
/// \brief Note that this member template is a specialization.
|
|
void setMemberSpecialization() {
|
|
assert(getCommonPtr()->InstantiatedFromMember.getPointer() &&
|
|
"Only member templates can be member template specializations");
|
|
getCommonPtr()->InstantiatedFromMember.setInt(true);
|
|
}
|
|
|
|
/// 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 classofKind(D->getKind()); }
|
|
static bool classof(const FunctionTemplateDecl *D) { return true; }
|
|
static bool classofKind(Kind K) { return K == FunctionTemplate; }
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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 default template argument, if any.
|
|
TypeSourceInfo *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 != 0; }
|
|
|
|
/// \brief Retrieve the default argument, if any.
|
|
QualType getDefaultArgument() const { return DefaultArgument->getType(); }
|
|
|
|
/// \brief Retrieves the default argument's source information, if any.
|
|
TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; }
|
|
|
|
/// \brief Retrieves the location of the default argument declaration.
|
|
SourceLocation getDefaultArgumentLoc() const;
|
|
|
|
/// \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(TypeSourceInfo *DefArg, bool Inherited) {
|
|
DefaultArgument = DefArg;
|
|
InheritedDefault = Inherited;
|
|
}
|
|
|
|
/// \brief Removes the default argument of this template parameter.
|
|
void removeDefaultArgument() {
|
|
DefaultArgument = 0;
|
|
InheritedDefault = false;
|
|
}
|
|
|
|
/// \brief Retrieve the depth of the template parameter.
|
|
unsigned getDepth() const;
|
|
|
|
/// \brief Retrieve the index of the template parameter.
|
|
unsigned getIndex() const;
|
|
|
|
/// \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 classofKind(D->getKind()); }
|
|
static bool classof(const TemplateTypeParmDecl *D) { return true; }
|
|
static bool classofKind(Kind K) { return K == TemplateTypeParm; }
|
|
};
|
|
|
|
/// 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,
|
|
TypeSourceInfo *TInfo)
|
|
: VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None,
|
|
VarDecl::None),
|
|
TemplateParmPosition(D, P), DefaultArgument(0)
|
|
{ }
|
|
|
|
public:
|
|
static NonTypeTemplateParmDecl *
|
|
Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
|
|
unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo);
|
|
|
|
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 classofKind(D->getKind()); }
|
|
static bool classof(const NonTypeTemplateParmDecl *D) { return true; }
|
|
static bool classofKind(Kind K) { return K == NonTypeTemplateParm; }
|
|
};
|
|
|
|
/// 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.
|
|
TemplateArgumentLoc DefaultArgument;
|
|
|
|
TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L,
|
|
unsigned D, unsigned P,
|
|
IdentifierInfo *Id, TemplateParameterList *Params)
|
|
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
|
|
TemplateParmPosition(D, P), DefaultArgument()
|
|
{ }
|
|
|
|
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.getArgument().isNull();
|
|
}
|
|
|
|
/// \brief Retrieve the default argument, if any.
|
|
const TemplateArgumentLoc &getDefaultArgument() const {
|
|
return DefaultArgument;
|
|
}
|
|
|
|
/// \brief Set the default argument for this template parameter.
|
|
void setDefaultArgument(const TemplateArgumentLoc &DefArg) {
|
|
DefaultArgument = DefArg;
|
|
}
|
|
|
|
// Implement isa/cast/dyncast/etc.
|
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
|
static bool classof(const TemplateTemplateParmDecl *D) { return true; }
|
|
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
|
|
};
|
|
|
|
/// \brief Represents a class template specialization, which refers to
|
|
/// a class template with a given set of template arguments.
|
|
///
|
|
/// Class template specializations represent both explicit
|
|
/// specialization of class templates, as in the example below, and
|
|
/// implicit instantiations of class templates.
|
|
///
|
|
/// \code
|
|
/// template<typename T> class array;
|
|
///
|
|
/// template<>
|
|
/// class array<bool> { }; // class template specialization array<bool>
|
|
/// \endcode
|
|
class ClassTemplateSpecializationDecl
|
|
: public CXXRecordDecl, public llvm::FoldingSetNode {
|
|
|
|
/// \brief Structure that stores information about a class template
|
|
/// specialization that was instantiated from a class template partial
|
|
/// specialization.
|
|
struct SpecializedPartialSpecialization {
|
|
/// \brief The class template partial specialization from which this
|
|
/// class template specialization was instantiated.
|
|
ClassTemplatePartialSpecializationDecl *PartialSpecialization;
|
|
|
|
/// \brief The template argument list deduced for the class template
|
|
/// partial specialization itself.
|
|
TemplateArgumentList *TemplateArgs;
|
|
};
|
|
|
|
/// \brief The template that this specialization specializes
|
|
llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *>
|
|
SpecializedTemplate;
|
|
|
|
/// \brief The type-as-written of an explicit template specialization.
|
|
/// Does not apply to implicit specializations.
|
|
TypeSourceInfo *TypeAsWritten;
|
|
|
|
/// \brief The template arguments used to describe this specialization.
|
|
TemplateArgumentList TemplateArgs;
|
|
|
|
/// \brief The point where this template was instantiated (if any)
|
|
SourceLocation PointOfInstantiation;
|
|
|
|
/// \brief The kind of specialization this declaration refers to.
|
|
/// Really a value of type TemplateSpecializationKind.
|
|
unsigned SpecializationKind : 3;
|
|
|
|
protected:
|
|
ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK,
|
|
DeclContext *DC, SourceLocation L,
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
TemplateArgumentListBuilder &Builder,
|
|
ClassTemplateSpecializationDecl *PrevDecl);
|
|
|
|
public:
|
|
static ClassTemplateSpecializationDecl *
|
|
Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L,
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
TemplateArgumentListBuilder &Builder,
|
|
ClassTemplateSpecializationDecl *PrevDecl);
|
|
|
|
virtual void Destroy(ASTContext& C);
|
|
|
|
virtual void getNameForDiagnostic(std::string &S,
|
|
const PrintingPolicy &Policy,
|
|
bool Qualified) const;
|
|
|
|
/// \brief Retrieve the template that this specialization specializes.
|
|
ClassTemplateDecl *getSpecializedTemplate() const;
|
|
|
|
/// \brief Retrieve the template arguments of the class template
|
|
/// specialization.
|
|
const TemplateArgumentList &getTemplateArgs() const {
|
|
return TemplateArgs;
|
|
}
|
|
|
|
/// \brief Determine the kind of specialization that this
|
|
/// declaration represents.
|
|
TemplateSpecializationKind getSpecializationKind() const {
|
|
return static_cast<TemplateSpecializationKind>(SpecializationKind);
|
|
}
|
|
|
|
void setSpecializationKind(TemplateSpecializationKind TSK) {
|
|
SpecializationKind = TSK;
|
|
}
|
|
|
|
/// \brief Get the point of instantiation (if any), or null if none.
|
|
SourceLocation getPointOfInstantiation() const {
|
|
return PointOfInstantiation;
|
|
}
|
|
|
|
void setPointOfInstantiation(SourceLocation Loc) {
|
|
assert(Loc.isValid() && "point of instantiation must be valid!");
|
|
PointOfInstantiation = Loc;
|
|
}
|
|
|
|
/// \brief If this class template specialization is an instantiation of
|
|
/// a template (rather than an explicit specialization), return the
|
|
/// class template or class template partial specialization from which it
|
|
/// was instantiated.
|
|
llvm::PointerUnion<ClassTemplateDecl *,
|
|
ClassTemplatePartialSpecializationDecl *>
|
|
getInstantiatedFrom() const {
|
|
if (getSpecializationKind() != TSK_ImplicitInstantiation &&
|
|
getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
|
|
getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
|
|
return (ClassTemplateDecl*)0;
|
|
|
|
if (SpecializedPartialSpecialization *PartialSpec
|
|
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
|
return PartialSpec->PartialSpecialization;
|
|
|
|
return const_cast<ClassTemplateDecl*>(
|
|
SpecializedTemplate.get<ClassTemplateDecl*>());
|
|
}
|
|
|
|
/// \brief Retrieve the set of template arguments that should be used
|
|
/// to instantiate members of the class template or class template partial
|
|
/// specialization from which this class template specialization was
|
|
/// instantiated.
|
|
///
|
|
/// \returns For a class template specialization instantiated from the primary
|
|
/// template, this function will return the same template arguments as
|
|
/// getTemplateArgs(). For a class template specialization instantiated from
|
|
/// a class template partial specialization, this function will return the
|
|
/// deduced template arguments for the class template partial specialization
|
|
/// itself.
|
|
const TemplateArgumentList &getTemplateInstantiationArgs() const {
|
|
if (SpecializedPartialSpecialization *PartialSpec
|
|
= SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>())
|
|
return *PartialSpec->TemplateArgs;
|
|
|
|
return getTemplateArgs();
|
|
}
|
|
|
|
/// \brief Note that this class template specialization is actually an
|
|
/// instantiation of the given class template partial specialization whose
|
|
/// template arguments have been deduced.
|
|
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
|
|
TemplateArgumentList *TemplateArgs) {
|
|
SpecializedPartialSpecialization *PS
|
|
= new (getASTContext()) SpecializedPartialSpecialization();
|
|
PS->PartialSpecialization = PartialSpec;
|
|
PS->TemplateArgs = TemplateArgs;
|
|
SpecializedTemplate = PS;
|
|
}
|
|
|
|
/// \brief Sets the type of this specialization as it was written by
|
|
/// the user. This will be a class template specialization type.
|
|
void setTypeAsWritten(TypeSourceInfo *T) {
|
|
TypeAsWritten = T;
|
|
}
|
|
|
|
/// \brief Gets the type of this specialization as it was written by
|
|
/// the user, if it was so written.
|
|
TypeSourceInfo *getTypeAsWritten() const {
|
|
return TypeAsWritten;
|
|
}
|
|
|
|
void Profile(llvm::FoldingSetNodeID &ID) const {
|
|
Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(),
|
|
getASTContext());
|
|
}
|
|
|
|
static void
|
|
Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs,
|
|
unsigned NumTemplateArgs, ASTContext &Context) {
|
|
ID.AddInteger(NumTemplateArgs);
|
|
for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg)
|
|
TemplateArgs[Arg].Profile(ID, Context);
|
|
}
|
|
|
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
|
static bool classofKind(Kind K) {
|
|
return K == ClassTemplateSpecialization ||
|
|
K == ClassTemplatePartialSpecialization;
|
|
}
|
|
|
|
static bool classof(const ClassTemplateSpecializationDecl *) {
|
|
return true;
|
|
}
|
|
|
|
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
class ClassTemplatePartialSpecializationDecl
|
|
: public ClassTemplateSpecializationDecl {
|
|
/// \brief The list of template parameters
|
|
TemplateParameterList* TemplateParams;
|
|
|
|
/// \brief The source info for the template arguments as written.
|
|
/// FIXME: redundant with TypeAsWritten?
|
|
TemplateArgumentLoc *ArgsAsWritten;
|
|
unsigned NumArgsAsWritten;
|
|
|
|
/// \brief Sequence number indicating when this class template partial
|
|
/// specialization was added to the set of partial specializations for
|
|
/// its owning class template.
|
|
unsigned SequenceNumber;
|
|
|
|
/// \brief The class template partial specialization from which this
|
|
/// class template partial specialization was instantiated.
|
|
///
|
|
/// The boolean value will be true to indicate that this class template
|
|
/// partial specialization was specialized at this level.
|
|
llvm::PointerIntPair<ClassTemplatePartialSpecializationDecl *, 1, bool>
|
|
InstantiatedFromMember;
|
|
|
|
ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK,
|
|
DeclContext *DC, SourceLocation L,
|
|
TemplateParameterList *Params,
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
TemplateArgumentListBuilder &Builder,
|
|
TemplateArgumentLoc *ArgInfos,
|
|
unsigned NumArgInfos,
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl,
|
|
unsigned SequenceNumber)
|
|
: ClassTemplateSpecializationDecl(Context,
|
|
ClassTemplatePartialSpecialization,
|
|
TK, DC, L, SpecializedTemplate, Builder,
|
|
PrevDecl),
|
|
TemplateParams(Params), ArgsAsWritten(ArgInfos),
|
|
NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber),
|
|
InstantiatedFromMember(0, false) { }
|
|
|
|
public:
|
|
static ClassTemplatePartialSpecializationDecl *
|
|
Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L,
|
|
TemplateParameterList *Params,
|
|
ClassTemplateDecl *SpecializedTemplate,
|
|
TemplateArgumentListBuilder &Builder,
|
|
const TemplateArgumentListInfo &ArgInfos,
|
|
QualType CanonInjectedType,
|
|
ClassTemplatePartialSpecializationDecl *PrevDecl,
|
|
unsigned SequenceNumber);
|
|
|
|
/// Get the list of template parameters
|
|
TemplateParameterList *getTemplateParameters() const {
|
|
return TemplateParams;
|
|
}
|
|
|
|
/// Get the template arguments as written.
|
|
TemplateArgumentLoc *getTemplateArgsAsWritten() const {
|
|
return ArgsAsWritten;
|
|
}
|
|
|
|
/// Get the number of template arguments as written.
|
|
unsigned getNumTemplateArgsAsWritten() const {
|
|
return NumArgsAsWritten;
|
|
}
|
|
|
|
/// \brief Get the sequence number for this class template partial
|
|
/// specialization.
|
|
unsigned getSequenceNumber() const { return SequenceNumber; }
|
|
|
|
/// \brief Retrieve the member class template partial specialization from
|
|
/// which this particular class template partial specialization was
|
|
/// instantiated.
|
|
///
|
|
/// \code
|
|
/// template<typename T>
|
|
/// struct Outer {
|
|
/// template<typename U> struct Inner;
|
|
/// template<typename U> struct Inner<U*> { }; // #1
|
|
/// };
|
|
///
|
|
/// Outer<float>::Inner<int*> ii;
|
|
/// \endcode
|
|
///
|
|
/// In this example, the instantiation of \c Outer<float>::Inner<int*> will
|
|
/// end up instantiating the partial specialization
|
|
/// \c Outer<float>::Inner<U*>, which itself was instantiated from the class
|
|
/// template partial specialization \c Outer<T>::Inner<U*>. Given
|
|
/// \c Outer<float>::Inner<U*>, this function would return
|
|
/// \c Outer<T>::Inner<U*>.
|
|
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
|
|
ClassTemplatePartialSpecializationDecl *First
|
|
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
|
return First->InstantiatedFromMember.getPointer();
|
|
}
|
|
|
|
void setInstantiatedFromMember(
|
|
ClassTemplatePartialSpecializationDecl *PartialSpec) {
|
|
ClassTemplatePartialSpecializationDecl *First
|
|
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
|
First->InstantiatedFromMember.setPointer(PartialSpec);
|
|
}
|
|
|
|
/// \brief Determines whether this class template partial specialization
|
|
/// template was a specialization of a member partial specialization.
|
|
///
|
|
/// In the following example, the member template partial specialization
|
|
/// \c X<int>::Inner<T*> is a member specialization.
|
|
///
|
|
/// \code
|
|
/// template<typename T>
|
|
/// struct X {
|
|
/// template<typename U> struct Inner;
|
|
/// template<typename U> struct Inner<U*>;
|
|
/// };
|
|
///
|
|
/// template<> template<typename T>
|
|
/// struct X<int>::Inner<T*> { /* ... */ };
|
|
/// \endcode
|
|
bool isMemberSpecialization() {
|
|
ClassTemplatePartialSpecializationDecl *First
|
|
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
|
return First->InstantiatedFromMember.getInt();
|
|
}
|
|
|
|
/// \brief Note that this member template is a specialization.
|
|
void setMemberSpecialization() {
|
|
ClassTemplatePartialSpecializationDecl *First
|
|
= cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
|
|
assert(First->InstantiatedFromMember.getPointer() &&
|
|
"Only member templates can be member template specializations");
|
|
return First->InstantiatedFromMember.setInt(true);
|
|
}
|
|
|
|
/// Retrieves the injected specialization type for this partial
|
|
/// specialization. This is not the same as the type-decl-type for
|
|
/// this partial specialization, which is an InjectedClassNameType.
|
|
QualType getInjectedSpecializationType() const {
|
|
assert(getTypeForDecl() && "partial specialization has no type set!");
|
|
return cast<InjectedClassNameType>(getTypeForDecl())
|
|
->getInjectedSpecializationType();
|
|
}
|
|
|
|
// FIXME: Add Profile support!
|
|
|
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
|
static bool classofKind(Kind K) {
|
|
return K == ClassTemplatePartialSpecialization;
|
|
}
|
|
|
|
static bool classof(const ClassTemplatePartialSpecializationDecl *) {
|
|
return true;
|
|
}
|
|
};
|
|
|
|
/// Declaration of a class template.
|
|
class ClassTemplateDecl : public TemplateDecl {
|
|
static void DeallocateCommon(void *Ptr);
|
|
|
|
protected:
|
|
/// \brief Data that is common to all of the declarations of a given
|
|
/// class template.
|
|
struct Common {
|
|
Common() : InstantiatedFromMember(0, 0) {}
|
|
|
|
/// \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;
|
|
|
|
/// \brief The templated member class from which this was most
|
|
/// directly instantiated (or null).
|
|
///
|
|
/// The boolean value indicates whether this member class template
|
|
/// was explicitly specialized.
|
|
llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember;
|
|
};
|
|
|
|
// FIXME: Combine PreviousDeclaration with CommonPtr, as in
|
|
// FunctionTemplateDecl.
|
|
|
|
/// \brief Previous declaration of this class template.
|
|
ClassTemplateDecl *PreviousDeclaration;
|
|
|
|
/// \brief Pointer to the data that is common to all of the
|
|
/// declarations of this class template.
|
|
///
|
|
/// The first declaration of a class template (e.g., the declaration
|
|
/// with no "previous declaration") owns this pointer.
|
|
Common *CommonPtr;
|
|
|
|
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
TemplateParameterList *Params, NamedDecl *Decl,
|
|
ClassTemplateDecl *PrevDecl, Common *CommonPtr)
|
|
: TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
|
|
PreviousDeclaration(PrevDecl), CommonPtr(CommonPtr) { }
|
|
|
|
~ClassTemplateDecl();
|
|
|
|
public:
|
|
/// Get the underlying class declarations of the template.
|
|
CXXRecordDecl *getTemplatedDecl() const {
|
|
return static_cast<CXXRecordDecl *>(TemplatedDecl);
|
|
}
|
|
|
|
/// \brief Retrieve the previous declaration of this template.
|
|
ClassTemplateDecl *getPreviousDeclaration() const {
|
|
return PreviousDeclaration;
|
|
}
|
|
|
|
virtual ClassTemplateDecl *getCanonicalDecl();
|
|
|
|
/// Create a class template node.
|
|
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
|
SourceLocation L,
|
|
DeclarationName Name,
|
|
TemplateParameterList *Params,
|
|
NamedDecl *Decl,
|
|
ClassTemplateDecl *PrevDecl);
|
|
|
|
/// \brief Retrieve the set of specializations of this class template.
|
|
llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
|
|
return CommonPtr->Specializations;
|
|
}
|
|
|
|
/// \brief Retrieve the set of partial specializations of this class
|
|
/// template.
|
|
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
|
|
getPartialSpecializations() {
|
|
return CommonPtr->PartialSpecializations;
|
|
}
|
|
|
|
/// \brief Retrieve the partial specializations as an ordered list.
|
|
void getPartialSpecializations(
|
|
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
|
|
|
|
/// \brief Find a class template partial specialization with the given
|
|
/// type T.
|
|
///
|
|
/// \brief A dependent type that names a specialization of this class
|
|
/// template.
|
|
///
|
|
/// \returns the class template partial specialization that exactly matches
|
|
/// the type \p T, or NULL if no such partial specialization exists.
|
|
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
|
|
|
|
/// \brief Retrieve the template specialization type of the
|
|
/// injected-class-name for this class template.
|
|
///
|
|
/// The injected-class-name for a class template \c X is \c
|
|
/// X<template-args>, where \c template-args is formed from the
|
|
/// template arguments that correspond to the template parameters of
|
|
/// \c X. For example:
|
|
///
|
|
/// \code
|
|
/// template<typename T, int N>
|
|
/// struct array {
|
|
/// typedef array this_type; // "array" is equivalent to "array<T, N>"
|
|
/// };
|
|
/// \endcode
|
|
QualType getInjectedClassNameSpecialization(ASTContext &Context);
|
|
|
|
/// \brief Retrieve the member class template that this class template was
|
|
/// derived from.
|
|
///
|
|
/// This routine will return non-NULL for templated member classes of
|
|
/// class templates. For example, given:
|
|
///
|
|
/// \code
|
|
/// template <typename T>
|
|
/// struct X {
|
|
/// template <typename U> struct A {};
|
|
/// };
|
|
/// \endcode
|
|
///
|
|
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
|
|
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
|
|
/// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
|
|
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
|
/// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD).
|
|
///
|
|
/// \returns null if this is not an instantiation of a member class template.
|
|
ClassTemplateDecl *getInstantiatedFromMemberTemplate() const {
|
|
return CommonPtr->InstantiatedFromMember.getPointer();
|
|
}
|
|
|
|
void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) {
|
|
assert(!CommonPtr->InstantiatedFromMember.getPointer());
|
|
CommonPtr->InstantiatedFromMember.setPointer(CTD);
|
|
}
|
|
|
|
/// \brief Determines whether this template was a specialization of a
|
|
/// member template.
|
|
///
|
|
/// In the following example, the member template \c X<int>::Inner is a
|
|
/// member specialization.
|
|
///
|
|
/// \code
|
|
/// template<typename T>
|
|
/// struct X {
|
|
/// template<typename U> struct Inner;
|
|
/// };
|
|
///
|
|
/// template<> template<typename T>
|
|
/// struct X<int>::Inner { /* ... */ };
|
|
/// \endcode
|
|
bool isMemberSpecialization() {
|
|
return CommonPtr->InstantiatedFromMember.getInt();
|
|
}
|
|
|
|
/// \brief Note that this member template is a specialization.
|
|
void setMemberSpecialization() {
|
|
assert(CommonPtr->InstantiatedFromMember.getPointer() &&
|
|
"Only member templates can be member template specializations");
|
|
CommonPtr->InstantiatedFromMember.setInt(true);
|
|
}
|
|
|
|
// Implement isa/cast/dyncast support
|
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
|
static bool classof(const ClassTemplateDecl *D) { return true; }
|
|
static bool classofKind(Kind K) { return K == ClassTemplate; }
|
|
|
|
virtual void Destroy(ASTContext& C);
|
|
};
|
|
|
|
/// Declaration of a friend template. For example:
|
|
///
|
|
/// template <typename T> class A {
|
|
/// friend class MyVector<T>; // not a friend template
|
|
/// template <typename U> friend class B; // friend template
|
|
/// template <typename U> friend class Foo<T>::Nested; // friend template
|
|
class FriendTemplateDecl : public Decl {
|
|
public:
|
|
typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;
|
|
|
|
private:
|
|
// The number of template parameters; always non-zero.
|
|
unsigned NumParams;
|
|
|
|
// The parameter list.
|
|
TemplateParameterList **Params;
|
|
|
|
// The declaration that's a friend of this class.
|
|
FriendUnion Friend;
|
|
|
|
// Location of the 'friend' specifier.
|
|
SourceLocation FriendLoc;
|
|
|
|
|
|
FriendTemplateDecl(DeclContext *DC, SourceLocation Loc,
|
|
unsigned NParams,
|
|
TemplateParameterList **Params,
|
|
FriendUnion Friend,
|
|
SourceLocation FriendLoc)
|
|
: Decl(Decl::FriendTemplate, DC, Loc),
|
|
NumParams(NParams),
|
|
Params(Params),
|
|
Friend(Friend),
|
|
FriendLoc(FriendLoc)
|
|
{}
|
|
|
|
public:
|
|
static FriendTemplateDecl *Create(ASTContext &Context,
|
|
DeclContext *DC, SourceLocation Loc,
|
|
unsigned NParams,
|
|
TemplateParameterList **Params,
|
|
FriendUnion Friend,
|
|
SourceLocation FriendLoc);
|
|
|
|
/// If this friend declaration names a templated type (or
|
|
/// a dependent member type of a templated type), return that
|
|
/// type; otherwise return null.
|
|
TypeSourceInfo *getFriendType() const {
|
|
return Friend.dyn_cast<TypeSourceInfo*>();
|
|
}
|
|
|
|
/// If this friend declaration names a templated function (or
|
|
/// a member function of a templated type), return that type;
|
|
/// otherwise return null.
|
|
NamedDecl *getFriendDecl() const {
|
|
return Friend.dyn_cast<NamedDecl*>();
|
|
}
|
|
|
|
/// Retrieves the location of the 'friend' keyword.
|
|
SourceLocation getFriendLoc() const {
|
|
return FriendLoc;
|
|
}
|
|
|
|
TemplateParameterList *getTemplateParameterList(unsigned i) const {
|
|
assert(i <= NumParams);
|
|
return Params[i];
|
|
}
|
|
|
|
unsigned getNumTemplateParameters() const {
|
|
return NumParams;
|
|
}
|
|
|
|
// Implement isa/cast/dyncast/etc.
|
|
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
|
|
static bool classofKind(Kind K) { return K == Decl::FriendTemplate; }
|
|
static bool classof(const FriendTemplateDecl *D) { return true; }
|
|
};
|
|
|
|
/// Implementation of inline functions that require the template declarations
|
|
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
|
|
: Function(FTD) { }
|
|
|
|
} /* end of namespace clang */
|
|
|
|
#endif
|