summaryrefslogtreecommitdiffstats
path: root/include/clang/AST/DeclTemplate.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclTemplate.h')
-rw-r--r--include/clang/AST/DeclTemplate.h691
1 files changed, 630 insertions, 61 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index 425a617..24bd28a 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -34,6 +34,8 @@ class TemplateTypeParmDecl;
class NonTypeTemplateParmDecl;
class TemplateTemplateParmDecl;
class TypeAliasTemplateDecl;
+class VarTemplateDecl;
+class VarTemplatePartialSpecializationDecl;
/// \brief Stores a template parameter of any kind.
typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*,
@@ -629,9 +631,9 @@ public:
template <class decl_type> friend class RedeclarableTemplate;
/// \brief Retrieves the canonical declaration of this template.
- RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); }
- const RedeclarableTemplateDecl *getCanonicalDecl() const {
- return getFirstDeclaration();
+ RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDecl(); }
+ const RedeclarableTemplateDecl *getCanonicalDecl() const {
+ return getFirstDecl();
}
/// \brief Determines whether this template was a specialization of a
@@ -713,6 +715,7 @@ public:
using redeclarable_base::redecls_end;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
+ using redeclarable_base::isFirstDecl;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -743,7 +746,7 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
- Common() : InjectedArgs(0) { }
+ Common() : InjectedArgs(), LazySpecializations() { }
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
@@ -757,6 +760,13 @@ protected:
/// template, and is allocated lazily, since most function templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs;
+
+ /// \brief If non-null, points to an array of specializations known only
+ /// by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations
+ /// that follow.
+ uint32_t *LazySpecializations;
};
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
@@ -771,12 +781,13 @@ protected:
friend class FunctionDecl;
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
- getSpecializations() const {
- return getCommonPtr()->Specializations;
- }
+ getSpecializations() const;
/// \brief Add a specialization of this function template.
///
@@ -815,14 +826,14 @@ public:
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDecl() {
return cast_or_null<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDecl() const {
return cast_or_null<FunctionTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -847,7 +858,7 @@ public:
/// arguments for a function template, the notion is convenient when
/// we need to perform substitutions inside the definition of a function
/// template.
- std::pair<const TemplateArgument *, unsigned> getInjectedTemplateArgs();
+ ArrayRef<TemplateArgument> getInjectedTemplateArgs();
/// \brief Create a function template node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1377,7 +1388,7 @@ class ClassTemplateSpecializationDecl
/// \brief The template argument list deduced for the class template
/// partial specialization itself.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
};
/// \brief The template that this specialization specializes
@@ -1402,7 +1413,7 @@ class ClassTemplateSpecializationDecl
ExplicitSpecializationInfo *ExplicitInfo;
/// \brief The template arguments used to describe this specialization.
- TemplateArgumentList *TemplateArgs;
+ const TemplateArgumentList *TemplateArgs;
/// \brief The point where this template was instantiated (if any)
SourceLocation PointOfInstantiation;
@@ -1438,9 +1449,9 @@ public:
bool Qualified) const;
ClassTemplateSpecializationDecl *getMostRecentDecl() {
- CXXRecordDecl *Recent
- = cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDecl());
- if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
+ CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>(
+ this)->getMostRecentDecl();
+ while (!isa<ClassTemplateSpecializationDecl>(Recent)) {
// FIXME: Does injected class name need to be in the redeclarations chain?
assert(Recent->isInjectedClassName() && Recent->getPreviousDecl());
Recent = Recent->getPreviousDecl();
@@ -1553,7 +1564,7 @@ public:
/// instantiation of the given class template partial specialization whose
/// template arguments have been deduced.
void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec,
- TemplateArgumentList *TemplateArgs) {
+ const TemplateArgumentList *TemplateArgs) {
assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() &&
"Already set to a class template partial specialization!");
SpecializedPartialSpecialization *PS
@@ -1639,13 +1650,7 @@ class ClassTemplatePartialSpecializationDecl
/// \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;
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
/// \brief The class template partial specialization from which this
/// class template partial specialization was instantiated.
@@ -1663,16 +1668,12 @@ class ClassTemplatePartialSpecializationDecl
ClassTemplateDecl *SpecializedTemplate,
const TemplateArgument *Args,
unsigned NumArgs,
- TemplateArgumentLoc *ArgInfos,
- unsigned NumArgInfos,
- ClassTemplatePartialSpecializationDecl *PrevDecl,
- unsigned SequenceNumber);
+ const ASTTemplateArgumentListInfo *ArgsAsWritten,
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
ClassTemplatePartialSpecializationDecl()
: ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization),
- TemplateParams(0), ArgsAsWritten(0),
- NumArgsAsWritten(0), SequenceNumber(0),
- InstantiatedFromMember(0, false) { }
+ TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) { }
public:
static ClassTemplatePartialSpecializationDecl *
@@ -1684,15 +1685,15 @@ public:
unsigned NumArgs,
const TemplateArgumentListInfo &ArgInfos,
QualType CanonInjectedType,
- ClassTemplatePartialSpecializationDecl *PrevDecl,
- unsigned SequenceNumber);
+ ClassTemplatePartialSpecializationDecl *PrevDecl);
static ClassTemplatePartialSpecializationDecl *
CreateDeserialized(ASTContext &C, unsigned ID);
ClassTemplatePartialSpecializationDecl *getMostRecentDecl() {
return cast<ClassTemplatePartialSpecializationDecl>(
- ClassTemplateSpecializationDecl::getMostRecentDecl());
+ static_cast<ClassTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
}
/// Get the list of template parameters
@@ -1701,19 +1702,10 @@ public:
}
/// Get the template arguments as written.
- TemplateArgumentLoc *getTemplateArgsAsWritten() const {
+ const ASTTemplateArgumentListInfo *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.
@@ -1735,15 +1727,15 @@ public:
/// \c Outer<float>::Inner<U*>, this function would return
/// \c Outer<T>::Inner<U*>.
ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getPointer();
}
void setInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *PartialSpec) {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
First->InstantiatedFromMember.setPointer(PartialSpec);
}
@@ -1764,15 +1756,15 @@ public:
/// struct X<int>::Inner<T*> { /* ... */ };
/// \endcode
bool isMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
return First->InstantiatedFromMember.getInt();
}
/// \brief Note that this member template is a specialization.
void setMemberSpecialization() {
- ClassTemplatePartialSpecializationDecl *First
- = cast<ClassTemplatePartialSpecializationDecl>(getFirstDeclaration());
+ ClassTemplatePartialSpecializationDecl *First =
+ cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl());
assert(First->InstantiatedFromMember.getPointer() &&
"Only member templates can be member template specializations");
return First->InstantiatedFromMember.setInt(true);
@@ -1821,7 +1813,7 @@ protected:
QualType InjectedClassNameType;
/// \brief If non-null, points to an array of specializations (including
- /// partial specializations) known ownly by their external declaration IDs.
+ /// partial specializations) known only by their external declaration IDs.
///
/// The first value in the array is the number of of specializations/
/// partial specializations that follow.
@@ -1900,14 +1892,23 @@ public:
/// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDecl() {
return cast_or_null<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDecl() const {
return cast_or_null<ClassTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ ClassTemplateDecl *getMostRecentDecl() {
+ return cast<ClassTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getMostRecentDecl());
+ }
+ const ClassTemplateDecl *getMostRecentDecl() const {
+ return const_cast<ClassTemplateDecl*>(this)->getMostRecentDecl();
}
ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -1926,11 +1927,6 @@ public:
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
void *InsertPos);
- /// \brief Return the next partial specialization sequence number.
- unsigned getNextPartialSpecSequenceNumber() {
- return getPartialSpecializations().size();
- }
-
/// \brief Retrieve the partial specializations as an ordered list.
void getPartialSpecializations(
SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS);
@@ -2139,14 +2135,15 @@ public:
/// NULL if no such declaration exists.
TypeAliasTemplateDecl *getPreviousDecl() {
return cast_or_null<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
const TypeAliasTemplateDecl *getPreviousDecl() const {
return cast_or_null<TypeAliasTemplateDecl>(
- RedeclarableTemplateDecl::getPreviousDecl());
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
}
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
@@ -2239,6 +2236,578 @@ public:
inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
: Function(FTD) { }
+/// \brief Represents a variable template specialization, which refers to
+/// a variable template with a given set of template arguments.
+///
+/// Variable template specializations represent both explicit
+/// specializations of variable templates, as in the example below, and
+/// implicit instantiations of variable templates.
+///
+/// \code
+/// template<typename T> constexpr T pi = T(3.1415926535897932385);
+///
+/// template<>
+/// constexpr float pi<float>; // variable template specialization pi<float>
+/// \endcode
+class VarTemplateSpecializationDecl : public VarDecl,
+ public llvm::FoldingSetNode {
+
+ /// \brief Structure that stores information about a variable template
+ /// specialization that was instantiated from a variable template partial
+ /// specialization.
+ struct SpecializedPartialSpecialization {
+ /// \brief The variable template partial specialization from which this
+ /// variable template specialization was instantiated.
+ VarTemplatePartialSpecializationDecl *PartialSpecialization;
+
+ /// \brief The template argument list deduced for the variable template
+ /// partial specialization itself.
+ const TemplateArgumentList *TemplateArgs;
+ };
+
+ /// \brief The template that this specialization specializes.
+ llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *>
+ SpecializedTemplate;
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ struct ExplicitSpecializationInfo {
+ /// \brief The type-as-written.
+ TypeSourceInfo *TypeAsWritten;
+ /// \brief The location of the extern keyword.
+ SourceLocation ExternLoc;
+ /// \brief The location of the template keyword.
+ SourceLocation TemplateKeywordLoc;
+
+ ExplicitSpecializationInfo()
+ : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {}
+ };
+
+ /// \brief Further info for explicit template specialization/instantiation.
+ /// Does not apply to implicit specializations.
+ ExplicitSpecializationInfo *ExplicitInfo;
+
+ /// \brief The template arguments used to describe this specialization.
+ const TemplateArgumentList *TemplateArgs;
+ TemplateArgumentListInfo TemplateArgsInfo;
+
+ /// \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:
+ VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ VarTemplateDecl *SpecializedTemplate,
+ QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ explicit VarTemplateSpecializationDecl(Kind DK);
+
+public:
+ static VarTemplateSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs);
+ static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ virtual void getNameForDiagnostic(raw_ostream &OS,
+ const PrintingPolicy &Policy,
+ bool Qualified) const;
+
+ VarTemplateSpecializationDecl *getMostRecentDecl() {
+ VarDecl *Recent = static_cast<VarDecl *>(this)->getMostRecentDecl();
+ return cast<VarTemplateSpecializationDecl>(Recent);
+ }
+
+ /// \brief Retrieve the template that this specialization specializes.
+ VarTemplateDecl *getSpecializedTemplate() const;
+
+ /// \brief Retrieve the template arguments of the variable template
+ /// specialization.
+ const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; }
+
+ // TODO: Always set this when creating the new specialization?
+ void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo);
+
+ const TemplateArgumentListInfo &getTemplateArgsInfo() const {
+ return TemplateArgsInfo;
+ }
+
+ /// \brief Determine the kind of specialization that this
+ /// declaration represents.
+ TemplateSpecializationKind getSpecializationKind() const {
+ return static_cast<TemplateSpecializationKind>(SpecializationKind);
+ }
+
+ bool isExplicitSpecialization() const {
+ return getSpecializationKind() == TSK_ExplicitSpecialization;
+ }
+
+ /// \brief True if this declaration is an explicit specialization,
+ /// explicit instantiation declaration, or explicit instantiation
+ /// definition.
+ bool isExplicitInstantiationOrSpecialization() const {
+ switch (getTemplateSpecializationKind()) {
+ case TSK_ExplicitSpecialization:
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ return true;
+
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ return false;
+ }
+ llvm_unreachable("bad template specialization kind");
+ }
+
+ 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 variable template specialization is an instantiation of
+ /// a template (rather than an explicit specialization), return the
+ /// variable template or variable template partial specialization from which
+ /// it was instantiated.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getInstantiatedFrom() const {
+ if (getSpecializationKind() != TSK_ImplicitInstantiation &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDefinition &&
+ getSpecializationKind() != TSK_ExplicitInstantiationDeclaration)
+ return llvm::PointerUnion<VarTemplateDecl *,
+ VarTemplatePartialSpecializationDecl *>();
+
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the variable template or variable template partial
+ /// specialization which was specialized by this.
+ llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>
+ getSpecializedTemplateOrPartial() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return PartialSpec->PartialSpecialization;
+
+ return SpecializedTemplate.get<VarTemplateDecl *>();
+ }
+
+ /// \brief Retrieve the set of template arguments that should be used
+ /// to instantiate the initializer of the variable template or variable
+ /// template partial specialization from which this variable template
+ /// specialization was instantiated.
+ ///
+ /// \returns For a variable template specialization instantiated from the
+ /// primary template, this function will return the same template arguments
+ /// as getTemplateArgs(). For a variable template specialization instantiated
+ /// from a variable template partial specialization, this function will the
+ /// return deduced template arguments for the variable template partial
+ /// specialization itself.
+ const TemplateArgumentList &getTemplateInstantiationArgs() const {
+ if (SpecializedPartialSpecialization *PartialSpec =
+ SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>())
+ return *PartialSpec->TemplateArgs;
+
+ return getTemplateArgs();
+ }
+
+ /// \brief Note that this variable template specialization is actually an
+ /// instantiation of the given variable template partial specialization whose
+ /// template arguments have been deduced.
+ void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec,
+ const TemplateArgumentList *TemplateArgs) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Already set to a variable template partial specialization!");
+ SpecializedPartialSpecialization *PS =
+ new (getASTContext()) SpecializedPartialSpecialization();
+ PS->PartialSpecialization = PartialSpec;
+ PS->TemplateArgs = TemplateArgs;
+ SpecializedTemplate = PS;
+ }
+
+ /// \brief Note that this variable template specialization is an instantiation
+ /// of the given variable template.
+ void setInstantiationOf(VarTemplateDecl *TemplDecl) {
+ assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() &&
+ "Previously set to a variable template partial specialization!");
+ SpecializedTemplate = TemplDecl;
+ }
+
+ /// \brief Sets the type of this specialization as it was written by
+ /// the user.
+ void setTypeAsWritten(TypeSourceInfo *T) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->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 ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0;
+ }
+
+ /// \brief Gets the location of the extern keyword, if present.
+ SourceLocation getExternLoc() const {
+ return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation();
+ }
+ /// \brief Sets the location of the extern keyword.
+ void setExternLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->ExternLoc = Loc;
+ }
+
+ /// \brief Sets the location of the template keyword.
+ void setTemplateKeywordLoc(SourceLocation Loc) {
+ if (!ExplicitInfo)
+ ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo;
+ ExplicitInfo->TemplateKeywordLoc = Loc;
+ }
+ /// \brief Gets the location of the template keyword, if present.
+ SourceLocation getTemplateKeywordLoc() const {
+ return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation();
+ }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ Profile(ID, TemplateArgs->data(), TemplateArgs->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 >= firstVarTemplateSpecialization &&
+ K <= lastVarTemplateSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+class VarTemplatePartialSpecializationDecl
+ : public VarTemplateSpecializationDecl {
+ virtual void anchor();
+
+ /// \brief The list of template parameters
+ TemplateParameterList *TemplateParams;
+
+ /// \brief The source info for the template arguments as written.
+ /// FIXME: redundant with TypeAsWritten?
+ const ASTTemplateArgumentListInfo *ArgsAsWritten;
+
+ /// \brief The variable template partial specialization from which this
+ /// variable template partial specialization was instantiated.
+ ///
+ /// The boolean value will be true to indicate that this variable template
+ /// partial specialization was specialized at this level.
+ llvm::PointerIntPair<VarTemplatePartialSpecializationDecl *, 1, bool>
+ InstantiatedFromMember;
+
+ VarTemplatePartialSpecializationDecl(
+ ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo,
+ StorageClass S, const TemplateArgument *Args, unsigned NumArgs,
+ const ASTTemplateArgumentListInfo *ArgInfos);
+
+ VarTemplatePartialSpecializationDecl()
+ : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization),
+ TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) {}
+
+public:
+ static VarTemplatePartialSpecializationDecl *
+ Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc,
+ SourceLocation IdLoc, TemplateParameterList *Params,
+ VarTemplateDecl *SpecializedTemplate, QualType T,
+ TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args,
+ unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos);
+
+ static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C,
+ unsigned ID);
+
+ VarTemplatePartialSpecializationDecl *getMostRecentDecl() {
+ return cast<VarTemplatePartialSpecializationDecl>(
+ static_cast<VarTemplateSpecializationDecl *>(
+ this)->getMostRecentDecl());
+ }
+
+ /// Get the list of template parameters
+ TemplateParameterList *getTemplateParameters() const {
+ return TemplateParams;
+ }
+
+ /// Get the template arguments as written.
+ const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
+ return ArgsAsWritten;
+ }
+
+ /// \brief Retrieve the member variable template partial specialization from
+ /// which this particular variable template partial specialization was
+ /// instantiated.
+ ///
+ /// \code
+ /// template<typename T>
+ /// struct Outer {
+ /// template<typename U> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0); // #1
+ /// };
+ ///
+ /// template int* Outer<float>::Inner<int*>;
+ /// \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
+ /// variable template partial specialization \c Outer<T>::Inner<U*>. Given
+ /// \c Outer<float>::Inner<U*>, this function would return
+ /// \c Outer<T>::Inner<U*>.
+ VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getPointer();
+ }
+
+ void
+ setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ First->InstantiatedFromMember.setPointer(PartialSpec);
+ }
+
+ /// \brief Determines whether this variable template partial specialization
+ /// 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> U Inner;
+ /// template<typename U> U* Inner<U*> = (U*)(0);
+ /// };
+ ///
+ /// template<> template<typename T>
+ /// U* X<int>::Inner<T*> = (T*)(0) + 1;
+ /// \endcode
+ bool isMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ return First->InstantiatedFromMember.getInt();
+ }
+
+ /// \brief Note that this member template is a specialization.
+ void setMemberSpecialization() {
+ VarTemplatePartialSpecializationDecl *First =
+ cast<VarTemplatePartialSpecializationDecl>(getFirstDecl());
+ assert(First->InstantiatedFromMember.getPointer() &&
+ "Only member templates can be member template specializations");
+ return First->InstantiatedFromMember.setInt(true);
+ }
+
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) {
+ return K == VarTemplatePartialSpecialization;
+ }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
+/// Declaration of a variable template.
+class VarTemplateDecl : public RedeclarableTemplateDecl {
+ static void DeallocateCommon(void *Ptr);
+
+protected:
+ /// \brief Data that is common to all of the declarations of a given
+ /// variable template.
+ struct Common : CommonBase {
+ Common() : LazySpecializations() {}
+
+ /// \brief The variable template specializations for this variable
+ /// template, including explicit specializations and instantiations.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations;
+
+ /// \brief The variable template partial specializations for this variable
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl>
+ PartialSpecializations;
+
+ /// \brief If non-null, points to an array of specializations (including
+ /// partial specializations) known ownly by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations/
+ /// partial specializations that follow.
+ uint32_t *LazySpecializations;
+ };
+
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
+ /// \brief Retrieve the set of specializations of this variable template.
+ llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
+ getSpecializations() const;
+
+ /// \brief Retrieve the set of partial specializations of this class
+ /// template.
+ llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
+ getPartialSpecializations();
+
+ VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl)
+ : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {}
+
+ VarTemplateDecl(EmptyShell Empty)
+ : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(),
+ DeclarationName(), 0, 0) {}
+
+ CommonBase *newCommon(ASTContext &C) const;
+
+ Common *getCommonPtr() const {
+ return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
+ }
+
+public:
+ /// \brief Get the underlying variable declarations of the template.
+ VarDecl *getTemplatedDecl() const {
+ return static_cast<VarDecl *>(TemplatedDecl);
+ }
+
+ /// \brief Returns whether this template declaration defines the primary
+ /// variable pattern.
+ bool isThisDeclarationADefinition() const {
+ return getTemplatedDecl()->isThisDeclarationADefinition();
+ }
+
+ VarTemplateDecl *getDefinition();
+
+ /// \brief Create a variable template node.
+ static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC,
+ SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, NamedDecl *Decl,
+ VarTemplateDecl *PrevDecl);
+
+ /// \brief Create an empty variable template node.
+ static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
+
+ /// \brief Return the specialization with the provided arguments if it exists,
+ /// otherwise return the insertion point.
+ VarTemplateSpecializationDecl *
+ findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified specialization knowing that it is not already
+ /// in. InsertPos must be obtained from findSpecialization.
+ void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos);
+
+ VarTemplateDecl *getCanonicalDecl() {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+ const VarTemplateDecl *getCanonicalDecl() const {
+ return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ VarTemplateDecl *getPreviousDecl() {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<RedeclarableTemplateDecl *>(this)->getPreviousDecl());
+ }
+
+ /// \brief Retrieve the previous declaration of this variable template, or
+ /// NULL if no such declaration exists.
+ const VarTemplateDecl *getPreviousDecl() const {
+ return cast_or_null<VarTemplateDecl>(
+ static_cast<const RedeclarableTemplateDecl *>(
+ this)->getPreviousDecl());
+ }
+
+ VarTemplateDecl *getInstantiatedFromMemberTemplate() {
+ return cast_or_null<VarTemplateDecl>(
+ RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
+ }
+
+ /// \brief Return the partial specialization with the provided arguments if it
+ /// exists, otherwise return the insertion point.
+ VarTemplatePartialSpecializationDecl *
+ findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
+ void *&InsertPos);
+
+ /// \brief Insert the specified partial specialization knowing that it is not
+ /// already in. InsertPos must be obtained from findPartialSpecialization.
+ void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D,
+ void *InsertPos);
+
+ /// \brief Retrieve the partial specializations as an ordered list.
+ void getPartialSpecializations(
+ SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS);
+
+ /// \brief Find a variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization.
+ ///
+ /// \param D a member variable template partial specialization.
+ ///
+ /// \returns the variable template partial specialization which was
+ /// instantiated
+ /// from the given member partial specialization, or NULL if no such partial
+ /// specialization exists.
+ VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember(
+ VarTemplatePartialSpecializationDecl *D);
+
+ typedef SpecIterator<VarTemplateSpecializationDecl> spec_iterator;
+
+ spec_iterator spec_begin() const {
+ return makeSpecIterator(getSpecializations(), false);
+ }
+
+ spec_iterator spec_end() const {
+ return makeSpecIterator(getSpecializations(), true);
+ }
+
+ typedef SpecIterator<VarTemplatePartialSpecializationDecl>
+ partial_spec_iterator;
+
+ partial_spec_iterator partial_spec_begin() {
+ return makeSpecIterator(getPartialSpecializations(), false);
+ }
+
+ partial_spec_iterator partial_spec_end() {
+ return makeSpecIterator(getPartialSpecializations(), true);
+ }
+
+ // Implement isa/cast/dyncast support
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }
+ static bool classofKind(Kind K) { return K == VarTemplate; }
+
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+};
+
} /* end of namespace clang */
#endif
OpenPOWER on IntegriCloud