diff options
Diffstat (limited to 'include/clang/AST/DeclTemplate.h')
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 691 |
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 |