//===-- 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. // //===----------------------------------------------------------------------===// /// /// \file /// \brief 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/Redeclarable.h" #include "clang/AST/TemplateBase.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" #include namespace clang { enum BuiltinTemplateKind : int; class TemplateParameterList; class TemplateDecl; class RedeclarableTemplateDecl; class FunctionTemplateDecl; class ClassTemplateDecl; class ClassTemplatePartialSpecializationDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; class TemplateTemplateParmDecl; class TypeAliasTemplateDecl; class VarTemplateDecl; class VarTemplatePartialSpecializationDecl; /// \brief Stores a template parameter of any kind. typedef llvm::PointerUnion3 TemplateParameter; NamedDecl *getAsNamedDecl(TemplateParameter P); /// \brief Stores a list of template parameters for a TemplateDecl and its /// derived classes. class TemplateParameterList final : private llvm::TrailingObjects { /// 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 : 30; /// Whether this template parameter list contains an unexpanded parameter /// pack. unsigned ContainsUnexpandedParameterPack : 1; /// Whether this template parameter list has an associated requires-clause unsigned HasRequiresClause : 1; protected: size_t numTrailingObjects(OverloadToken) const { return NumParams; } size_t numTrailingObjects(OverloadToken) const { return HasRequiresClause; } TemplateParameterList(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef Params, SourceLocation RAngleLoc, Expr *RequiresClause); public: static TemplateParameterList *Create(const ASTContext &C, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef Params, SourceLocation RAngleLoc, Expr *RequiresClause); /// \brief Iterates through the template parameters in this list. typedef NamedDecl** iterator; /// \brief Iterates through the template parameters in this list. typedef NamedDecl* const* const_iterator; iterator begin() { return getTrailingObjects(); } const_iterator begin() const { return getTrailingObjects(); } iterator end() { return begin() + NumParams; } const_iterator end() const { return begin() + NumParams; } unsigned size() const { return NumParams; } ArrayRef asArray() { return llvm::makeArrayRef(begin(), end()); } ArrayRef asArray() const { return llvm::makeArrayRef(begin(), size()); } 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]; } /// \brief 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; /// \brief Determine whether this template parameter list contains an /// unexpanded parameter pack. bool containsUnexpandedParameterPack() const { return ContainsUnexpandedParameterPack; } /// \brief The constraint-expression of the associated requires-clause. Expr *getRequiresClause() { return HasRequiresClause ? *getTrailingObjects() : nullptr; } /// \brief The constraint-expression of the associated requires-clause. const Expr *getRequiresClause() const { return HasRequiresClause ? *getTrailingObjects() : nullptr; } SourceLocation getTemplateLoc() const { return TemplateLoc; } SourceLocation getLAngleLoc() const { return LAngleLoc; } SourceLocation getRAngleLoc() const { return RAngleLoc; } SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(TemplateLoc, RAngleLoc); } friend TrailingObjects; template friend class FixedSizeTemplateParameterListStorage; public: // FIXME: workaround for MSVC 2013; remove when no longer needed using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner; }; /// \brief Stores a list of template parameters and the associated /// requires-clause (if any) for a TemplateDecl and its derived classes. /// Suitable for creating on the stack. template class FixedSizeTemplateParameterListStorage : public TemplateParameterList::FixedSizeStorageOwner { typename TemplateParameterList::FixedSizeStorage< NamedDecl *, Expr *>::with_counts< N, HasRequiresClause ? 1u : 0u >::type storage; public: FixedSizeTemplateParameterListStorage(SourceLocation TemplateLoc, SourceLocation LAngleLoc, ArrayRef Params, SourceLocation RAngleLoc, Expr *RequiresClause) : FixedSizeStorageOwner( (assert(N == Params.size()), assert(HasRequiresClause == static_cast(RequiresClause)), new (static_cast(&storage)) TemplateParameterList( TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {} }; /// \brief A template argument list. class TemplateArgumentList final : private llvm::TrailingObjects { /// \brief The template argument list. const TemplateArgument *Arguments; /// \brief The number of template arguments in this template /// argument list. unsigned NumArguments; TemplateArgumentList(const TemplateArgumentList &Other) = delete; void operator=(const TemplateArgumentList &Other) = delete; // Constructs an instance with an internal Argument list, containing // a copy of the Args array. (Called by CreateCopy) TemplateArgumentList(ArrayRef Args); public: /// \brief Type used to indicate that the template argument list itself is a /// stack object. It does not own its template arguments. enum OnStackType { OnStack }; /// \brief Create a new template argument list that copies the given set of /// template arguments. static TemplateArgumentList *CreateCopy(ASTContext &Context, ArrayRef Args); /// \brief Construct a new, temporary template argument list on the stack. /// /// The template argument list does not own the template arguments /// provided. explicit TemplateArgumentList(OnStackType, ArrayRef Args) : Arguments(Args.data()), NumArguments(Args.size()) {} /// \brief Produces a shallow copy of the given template argument list. /// /// This operation 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) : Arguments(Other->data()), NumArguments(Other->size()) {} /// \brief Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { assert(Idx < NumArguments && "Invalid template argument index"); return data()[Idx]; } /// \brief Retrieve the template argument at a given index. const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } /// \brief Produce this as an array ref. ArrayRef asArray() const { return llvm::makeArrayRef(data(), size()); } /// \brief Retrieve the number of template arguments in this /// template argument list. unsigned size() const { return NumArguments; } /// \brief Retrieve a pointer to the template argument list. const TemplateArgument *data() const { return Arguments; } friend TrailingObjects; }; void *allocateDefaultArgStorageChain(const ASTContext &C); /// Storage for a default argument. This is conceptually either empty, or an /// argument value, or a pointer to a previous declaration that had a default /// argument. /// /// However, this is complicated by modules: while we require all the default /// arguments for a template to be equivalent, there may be more than one, and /// we need to track all the originating parameters to determine if the default /// argument is visible. template class DefaultArgStorage { /// Storage for both the value *and* another parameter from which we inherit /// the default argument. This is used when multiple default arguments for a /// parameter are merged together from different modules. struct Chain { ParmDecl *PrevDeclWithDefaultArg; ArgType Value; }; static_assert(sizeof(Chain) == sizeof(void *) * 2, "non-pointer argument type?"); llvm::PointerUnion3 ValueOrInherited; static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); if (auto *Prev = Storage.ValueOrInherited.template dyn_cast()) Parm = Prev; assert(!Parm->getDefaultArgStorage() .ValueOrInherited.template is() && "should only be one level of indirection"); return Parm; } public: DefaultArgStorage() : ValueOrInherited(ArgType()) {} /// Determine whether there is a default argument for this parameter. bool isSet() const { return !ValueOrInherited.isNull(); } /// Determine whether the default argument for this parameter was inherited /// from a previous declaration of the same entity. bool isInherited() const { return ValueOrInherited.template is(); } /// Get the default argument's value. This does not consider whether the /// default argument is visible. ArgType get() const { const DefaultArgStorage *Storage = this; if (auto *Prev = ValueOrInherited.template dyn_cast()) Storage = &Prev->getDefaultArgStorage(); if (auto *C = Storage->ValueOrInherited.template dyn_cast()) return C->Value; return Storage->ValueOrInherited.template get(); } /// Get the parameter from which we inherit the default argument, if any. /// This is the parameter on which the default argument was actually written. const ParmDecl *getInheritedFrom() const { if (auto *D = ValueOrInherited.template dyn_cast()) return D; if (auto *C = ValueOrInherited.template dyn_cast()) return C->PrevDeclWithDefaultArg; return nullptr; } /// Set the default argument. void set(ArgType Arg) { assert(!isSet() && "default argument already set"); ValueOrInherited = Arg; } /// Set that the default argument was inherited from another parameter. void setInherited(const ASTContext &C, ParmDecl *InheritedFrom) { assert(!isInherited() && "default argument already inherited"); InheritedFrom = getParmOwningDefaultArg(InheritedFrom); if (!isSet()) ValueOrInherited = InheritedFrom; else ValueOrInherited = new (allocateDefaultArgStorageChain(C)) Chain{InheritedFrom, ValueOrInherited.template get()}; } /// Remove the default argument, even if it was inherited. void clear() { ValueOrInherited = ArgType(); } }; //===----------------------------------------------------------------------===// // Kinds of Templates //===----------------------------------------------------------------------===// /// \brief Stores the template parameter list and associated constraints for /// \c TemplateDecl objects that track associated constraints. class ConstrainedTemplateDeclInfo { friend TemplateDecl; public: ConstrainedTemplateDeclInfo() : TemplateParams(), AssociatedConstraints() {} TemplateParameterList *getTemplateParameters() const { return TemplateParams; } Expr *getAssociatedConstraints() const { return AssociatedConstraints; } protected: void setTemplateParameters(TemplateParameterList *TParams) { TemplateParams = TParams; } void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; } TemplateParameterList *TemplateParams; Expr *AssociatedConstraints; }; /// \brief 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 { void anchor() override; protected: // Construct a template decl with the given name and parameters. // Used when there is no templated element (e.g., for tt-params). TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), TemplateParams(CTDI) { this->setTemplateParameters(Params); } TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params) : TemplateDecl(nullptr, DK, DC, L, Name, Params) {} // Construct a template decl with name, parameters, and templated element. TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false), TemplateParams(CTDI) { this->setTemplateParameters(Params); } TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {} public: /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { const auto *const CTDI = TemplateParams.dyn_cast(); return CTDI ? CTDI->getTemplateParameters() : TemplateParams.get(); } /// Get the constraint-expression from the associated requires-clause (if any) const Expr *getRequiresClause() const { const TemplateParameterList *const TP = getTemplateParameters(); return TP ? TP->getRequiresClause() : nullptr; } Expr *getAssociatedConstraints() const { const TemplateDecl *const C = cast(getCanonicalDecl()); const auto *const CTDI = C->TemplateParams.dyn_cast(); return CTDI ? CTDI->getAssociatedConstraints() : nullptr; } /// Get the underlying, templated declaration. NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstTemplate && K <= lastTemplate; } SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getTemplateParameters()->getTemplateLoc(), TemplatedDecl.getPointer()->getSourceRange().getEnd()); } /// Whether this is a (C++ Concepts TS) function or variable concept. bool isConcept() const { return TemplatedDecl.getInt(); } void setConcept() { TemplatedDecl.setInt(true); } protected: /// \brief The named declaration from which this template was instantiated. /// (or null). /// /// The boolean value will be true to indicate that this template /// (function or variable) is a concept. llvm::PointerIntPair TemplatedDecl; /// \brief The template parameter list and optional requires-clause /// associated with this declaration; alternatively, a /// \c ConstrainedTemplateDeclInfo if the associated constraints of the /// template are being tracked by this particular declaration. llvm::PointerUnion TemplateParams; void setTemplateParameters(TemplateParameterList *TParams) { if (auto *const CTDI = TemplateParams.dyn_cast()) { CTDI->setTemplateParameters(TParams); } else { TemplateParams = TParams; } } void setAssociatedConstraints(Expr *AC) { assert(isCanonicalDecl() && "Attaching associated constraints to non-canonical Decl"); TemplateParams.get() ->setAssociatedConstraints(AC); } public: /// \brief Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!"); assert(!TemplateParams && "TemplateParams already set!"); TemplatedDecl.setPointer(templatedDecl); TemplateParams = 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 { FunctionTemplateSpecializationInfo(FunctionDecl *FD, FunctionTemplateDecl *Template, TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI) : Function(FD), Template(Template, TSK - 1), TemplateArguments(TemplateArgs), TemplateArgumentsAsWritten(TemplateArgsAsWritten), PointOfInstantiation(POI) { } public: static FunctionTemplateSpecializationInfo * Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI); /// \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 contain the top 4 values of TemplateSpecializationKind. llvm::PointerIntPair 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 ASTTemplateArgumentListInfo *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); } bool isExplicitSpecialization() const { return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; } /// \brief True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { return isTemplateExplicitInstantiationOrSpecialization( getTemplateSpecializationKind()); } /// \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->asArray(), Function->getASTContext()); } static void Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); for (const TemplateArgument &TemplateArg : TemplateArgs) TemplateArg.Profile(ID, Context); } }; /// \brief Provides information a specialization of a member of a class /// template, which may be a member function, static data member, /// member class or member enumeration. 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 MemberAndTSK; // The point at which this member was first instantiated. SourceLocation PointOfInstantiation; public: explicit MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK, SourceLocation POI = SourceLocation()) : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { 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); } bool isExplicitSpecialization() const { return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; } /// \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: /// /// \code /// template \ void foo(T); /// template \ class A { /// friend void foo<>(T); /// }; /// \endcode class DependentFunctionTemplateSpecializationInfo final : private llvm::TrailingObjects { /// The number of potential template candidates. unsigned NumTemplates; /// The number of template arguments. unsigned NumArgs; /// The locations of the left and right angle brackets. SourceRange AngleLocs; size_t numTrailingObjects(OverloadToken) const { return NumArgs; } size_t numTrailingObjects(OverloadToken) const { return NumTemplates; } DependentFunctionTemplateSpecializationInfo( const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs); public: static DependentFunctionTemplateSpecializationInfo * Create(ASTContext &Context, const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs); /// \brief Returns the number of function templates that this might /// be a specialization of. unsigned getNumTemplates() const { return NumTemplates; } /// \brief Returns the i'th template candidate. FunctionTemplateDecl *getTemplate(unsigned I) const { assert(I < getNumTemplates() && "template index out of range"); return getTrailingObjects()[I]; } /// \brief Returns the explicit template arguments that were given. const TemplateArgumentLoc *getTemplateArgs() const { return getTrailingObjects(); } /// \brief Returns the number of explicit template arguments that were given. unsigned getNumTemplateArgs() const { return 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(); } friend TrailingObjects; }; /// Declaration of a redeclarable template. class RedeclarableTemplateDecl : public TemplateDecl, public Redeclarable { typedef Redeclarable redeclarable_base; RedeclarableTemplateDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); } RedeclarableTemplateDecl *getPreviousDeclImpl() override { return getPreviousDecl(); } RedeclarableTemplateDecl *getMostRecentDeclImpl() override { return getMostRecentDecl(); } protected: template struct SpecEntryTraits { typedef EntryType DeclType; static DeclType *getDecl(EntryType *D) { return D; } static ArrayRef getTemplateArgs(EntryType *D) { return D->getTemplateArgs().asArray(); } }; template , typename DeclType = typename SETraits::DeclType> struct SpecIterator : llvm::iterator_adaptor_base< SpecIterator, typename llvm::FoldingSetVector::iterator, typename std::iterator_traits::iterator>::iterator_category, DeclType *, ptrdiff_t, DeclType *, DeclType *> { SpecIterator() {} explicit SpecIterator( typename llvm::FoldingSetVector::iterator SetIter) : SpecIterator::iterator_adaptor_base(std::move(SetIter)) {} DeclType *operator*() const { return SETraits::getDecl(&*this->I)->getMostRecentDecl(); } DeclType *operator->() const { return **this; } }; template static SpecIterator makeSpecIterator(llvm::FoldingSetVector &Specs, bool isEnd) { return SpecIterator(isEnd ? Specs.end() : Specs.begin()); } template typename SpecEntryTraits::DeclType* findSpecializationImpl(llvm::FoldingSetVector &Specs, ArrayRef Args, void *&InsertPos); template void addSpecializationImpl(llvm::FoldingSetVector &Specs, EntryType *Entry, void *InsertPos); struct CommonBase { CommonBase() : InstantiatedFromMember(nullptr, false) { } /// \brief The template from which this was most /// directly instantiated (or null). /// /// The boolean value indicates whether this template /// was explicitly specialized. llvm::PointerIntPair InstantiatedFromMember; }; /// \brief Pointer to the common data shared by all declarations of this /// template. mutable CommonBase *Common; /// \brief Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. CommonBase *getCommonPtr() const; virtual CommonBase *newCommon(ASTContext &C) const = 0; // Construct a template decl with name, parameters, and templated element. RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C), Common() {} RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {} public: template friend class RedeclarableTemplate; /// \brief Retrieves the canonical declaration of this template. RedeclarableTemplateDecl *getCanonicalDecl() override { return getFirstDecl(); } const RedeclarableTemplateDecl *getCanonicalDecl() const { return getFirstDecl(); } /// \brief Determines whether this template was a specialization of a /// member template. /// /// In the following example, the function template \c X::f and the /// member template \c X::Inner are member specializations. /// /// \code /// template /// struct X { /// template void f(T, U); /// template struct Inner; /// }; /// /// template<> template /// void X::f(int, T); /// template<> template /// struct X::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() const { 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); } /// \brief Retrieve the member template from which this template was /// instantiated, or NULL if this template was not instantiated from a /// member template. /// /// A template is instantiated from a member template when the member /// template itself is part of a class template (or member thereof). For /// example, given /// /// \code /// template /// struct X { /// template void f(T, U); /// }; /// /// void test(X x) { /// x.f(1, 'a'); /// }; /// \endcode /// /// \c X::f is a FunctionTemplateDecl that describes the function /// template /// /// \code /// template void X::f(int, U); /// \endcode /// /// which was itself created during the instantiation of \c X. Calling /// getInstantiatedFromMemberTemplate() on this FunctionTemplateDecl will /// retrieve the FunctionTemplateDecl for the original template \c f within /// the class template \c X, i.e., /// /// \code /// template /// template /// void X::f(T, U); /// \endcode RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() const { return getCommonPtr()->InstantiatedFromMember.getPointer(); } void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) { assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); getCommonPtr()->InstantiatedFromMember.setPointer(TD); } typedef redeclarable_base::redecl_range redecl_range; typedef redeclarable_base::redecl_iterator redecl_iterator; using redeclarable_base::redecls_begin; using redeclarable_base::redecls_end; using redeclarable_base::redecls; 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()); } static bool classofKind(Kind K) { return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; } friend class ASTReader; friend class ASTDeclReader; friend class ASTDeclWriter; }; template <> struct RedeclarableTemplateDecl:: SpecEntryTraits { typedef FunctionDecl DeclType; static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) { return I->Function; } static ArrayRef getTemplateArgs(FunctionTemplateSpecializationInfo *I) { return I->TemplateArguments->asArray(); } }; /// Declaration of a template function. class FunctionTemplateDecl : public RedeclarableTemplateDecl { protected: /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { Common() : InjectedArgs(), LazySpecializations() { } /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSetVector Specializations; /// \brief The set of "injected" template arguments used within this /// function template. /// /// This pointer refers to the template arguments (there are as /// many template arguments as template parameaters) for the function /// 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(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(FunctionTemplate, C, DC, L, Name, Params, Decl) {} CommonBase *newCommon(ASTContext &C) const override; Common *getCommonPtr() const { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } friend class FunctionDecl; /// \brief Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector & getSpecializations() const; /// \brief Add a specialization of this function template. /// /// \param InsertPos Insert position in the FoldingSetVector, must have been /// retrieved by an earlier call to findSpecialization(). void addSpecialization(FunctionTemplateSpecializationInfo* Info, void *InsertPos); public: /// \brief Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { return static_cast(TemplatedDecl.getPointer()); } /// Returns whether this template declaration defines the primary /// pattern. bool isThisDeclarationADefinition() const { return getTemplatedDecl()->isThisDeclarationADefinition(); } /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. FunctionDecl *findSpecialization(ArrayRef Args, void *&InsertPos); FunctionTemplateDecl *getCanonicalDecl() override { return cast( RedeclarableTemplateDecl::getCanonicalDecl()); } const FunctionTemplateDecl *getCanonicalDecl() const { return cast( RedeclarableTemplateDecl::getCanonicalDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. FunctionTemplateDecl *getPreviousDecl() { return cast_or_null( static_cast(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( static_cast(this)->getPreviousDecl()); } FunctionTemplateDecl *getMostRecentDecl() { return cast( static_cast(this) ->getMostRecentDecl()); } const FunctionTemplateDecl *getMostRecentDecl() const { return const_cast(this)->getMostRecentDecl(); } FunctionTemplateDecl *getInstantiatedFromMemberTemplate() const { return cast_or_null( RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } typedef SpecIterator spec_iterator; typedef llvm::iterator_range spec_range; spec_range specializations() const { return spec_range(spec_begin(), spec_end()); } spec_iterator spec_begin() const { return makeSpecIterator(getSpecializations(), false); } spec_iterator spec_end() const { return makeSpecIterator(getSpecializations(), true); } /// \brief Retrieve the "injected" template arguments that correspond to the /// template parameters of this function template. /// /// Although the C++ standard has no notion of the "injected" template /// arguments for a function template, the notion is convenient when /// we need to perform substitutions inside the definition of a function /// template. ArrayRef getInjectedTemplateArgs(); /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); /// \brief Create an empty function template node. static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == FunctionTemplate; } friend class ASTDeclReader; friend class ASTDeclWriter; }; //===----------------------------------------------------------------------===// // Kinds of Template Parameters //===----------------------------------------------------------------------===// /// \brief 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 { TemplateParmPosition() = delete; protected: 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; } void setDepth(unsigned D) { Depth = D; } /// Get the position of the template parameter within its parameter list. unsigned getPosition() const { return Position; } void setPosition(unsigned P) { Position = P; } /// Get the index of the template parameter within its parameter list. unsigned getIndex() const { return Position; } }; /// \brief Declaration of a template type parameter. /// /// For example, "T" in /// \code /// template 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 The default template argument, if any. typedef DefaultArgStorage DefArgStorage; DefArgStorage DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, SourceLocation IdLoc, IdentifierInfo *Id, bool Typename) : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, SourceLocation KeyLoc, SourceLocation NameLoc, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, unsigned ID); /// \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; } const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. QualType getDefaultArgument() const { return DefaultArgument.get()->getType(); } /// \brief Retrieves the default argument's source information, if any. TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument.get(); } /// \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 DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter. void setDefaultArgument(TypeSourceInfo *DefArg) { DefaultArgument.set(DefArg); } /// \brief Set that this default argument was inherited from another /// parameter. void setInheritedDefaultArgument(const ASTContext &C, TemplateTypeParmDecl *Prev) { DefaultArgument.setInherited(C, Prev); } /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } /// \brief Set whether this template type parameter was declared with /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } /// \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; SourceRange getSourceRange() const override LLVM_READONLY; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TemplateTypeParm; } }; /// NonTypeTemplateParmDecl - Declares a non-type template parameter, /// e.g., "Size" in /// @code /// template class array { }; /// @endcode class NonTypeTemplateParmDecl final : public DeclaratorDecl, protected TemplateParmPosition, private llvm::TrailingObjects> { /// \brief The default template argument, if any, and whether or not /// it was inherited. typedef DefaultArgStorage DefArgStorage; DefArgStorage DefaultArgument; // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index // down here to save memory. /// \brief Whether this non-type template parameter is a parameter pack. bool ParameterPack; /// \brief Whether this non-type template parameter is an "expanded" /// parameter pack, meaning that its type is a pack expansion and we /// already know the set of types that expansion expands to. bool ExpandedParameterPack; /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; size_t numTrailingObjects( OverloadToken>) const { return NumExpandedTypes; } NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), TemplateParmPosition(D, P), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedTypes(0) { } NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, ArrayRef ExpandedTypes, ArrayRef ExpandedTInfos); friend class ASTDeclReader; friend TrailingObjects; public: static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo); static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, ArrayRef ExpandedTypes, ArrayRef ExpandedTInfos); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumExpandedTypes); using TemplateParmPosition::getDepth; using TemplateParmPosition::setDepth; using TemplateParmPosition::getPosition; using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; SourceRange getSourceRange() const override LLVM_READONLY; const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } /// \brief Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument.isSet(); } /// \brief Retrieve the default argument, if any. Expr *getDefaultArgument() const { return DefaultArgument.get(); } /// \brief Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; /// \brief Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { return DefaultArgument.isInherited(); } /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } void setInheritedDefaultArgument(const ASTContext &C, NonTypeTemplateParmDecl *Parm) { DefaultArgument.setInherited(C, Parm); } /// \brief Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } /// \brief Whether this parameter is a non-type template parameter pack. /// /// If the parameter is a parameter pack, the type may be a /// \c PackExpansionType. In the following example, the \c Dims parameter /// is a parameter pack (whose type is 'unsigned'). /// /// \code /// template struct multi_array; /// \endcode bool isParameterPack() const { return ParameterPack; } /// \brief Whether this parameter pack is a pack expansion. /// /// A non-type template parameter pack is a pack expansion if its type /// contains an unexpanded parameter pack. In this case, we will have /// built a PackExpansionType wrapping the type. bool isPackExpansion() const { return ParameterPack && getType()->getAs(); } /// \brief Whether this parameter is a non-type template parameter pack /// that has a known list of different types at different positions. /// /// A parameter pack is an expanded parameter pack when the original /// parameter pack's type was itself a pack expansion, and that expansion /// has already been expanded. For example, given: /// /// \code /// template /// struct X { /// template /// struct Y { /* ... */ }; /// }; /// \endcode /// /// The parameter pack \c Values has a \c PackExpansionType as its type, /// which expands \c Types. When \c Types is supplied with template arguments /// by instantiating \c X, the instantiation of \c Values becomes an /// expanded parameter pack. For example, instantiating /// \c X results in \c Values being an expanded parameter /// pack with expansion types \c int and \c unsigned int. /// /// The \c getExpansionType() and \c getExpansionTypeSourceInfo() functions /// return the expansion types. bool isExpandedParameterPack() const { return ExpandedParameterPack; } /// \brief Retrieves the number of expansion types in an expanded parameter /// pack. unsigned getNumExpansionTypes() const { assert(ExpandedParameterPack && "Not an expansion parameter pack"); return NumExpandedTypes; } /// \brief Retrieve a particular expansion type within an expanded parameter /// pack. QualType getExpansionType(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); auto TypesAndInfos = getTrailingObjects>(); return TypesAndInfos[I].first; } /// \brief Retrieve a particular expansion type source info within an /// expanded parameter pack. TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); auto TypesAndInfos = getTrailingObjects>(); return TypesAndInfos[I].second; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == NonTypeTemplateParm; } }; /// TemplateTemplateParmDecl - Declares a template template parameter, /// e.g., "T" in /// @code /// template