diff options
Diffstat (limited to 'include/clang/AST/DeclTemplate.h')
-rw-r--r-- | include/clang/AST/DeclTemplate.h | 175 |
1 files changed, 126 insertions, 49 deletions
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f6e3d8f300..5933810ec8 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1,9 +1,8 @@ //===- 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. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -177,6 +176,11 @@ public: return SourceRange(TemplateLoc, RAngleLoc); } + void print(raw_ostream &Out, const ASTContext &Context, + bool OmitTemplateKW = false) const; + void print(raw_ostream &Out, const ASTContext &Context, + const PrintingPolicy &Policy, bool OmitTemplateKW = false) const; + public: // FIXME: workaround for MSVC 2013; remove when no longer needed using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner; @@ -505,29 +509,13 @@ public: /// 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); - - /// The function template specialization that this structure - /// describes. - FunctionDecl *Function; +class FunctionTemplateSpecializationInfo final + : public llvm::FoldingSetNode, + private llvm::TrailingObjects<FunctionTemplateSpecializationInfo, + MemberSpecializationInfo *> { + /// The function template specialization that this structure describes and a + /// flag indicating if the function is a member specialization. + llvm::PointerIntPair<FunctionDecl *, 1, bool> Function; /// The function template from which this function template /// specialization was generated. @@ -535,17 +523,50 @@ public: /// The two bits contain the top 4 values of TemplateSpecializationKind. llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template; +public: /// The template arguments used to produce the function template /// specialization from the function template. const TemplateArgumentList *TemplateArguments; /// The template arguments as written in the sources, if provided. + /// FIXME: Normally null; tail-allocate this. const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; /// The point at which this function template specialization was /// first instantiated. SourceLocation PointOfInstantiation; +private: + FunctionTemplateSpecializationInfo( + FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs, + const ASTTemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI, MemberSpecializationInfo *MSInfo) + : Function(FD, MSInfo ? 1 : 0), Template(Template, TSK - 1), + TemplateArguments(TemplateArgs), + TemplateArgumentsAsWritten(TemplateArgsAsWritten), + PointOfInstantiation(POI) { + if (MSInfo) + getTrailingObjects<MemberSpecializationInfo *>()[0] = MSInfo; + } + + size_t numTrailingObjects(OverloadToken<MemberSpecializationInfo*>) const { + return Function.getInt(); + } + +public: + friend TrailingObjects; + + static FunctionTemplateSpecializationInfo * + Create(ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template, + TemplateSpecializationKind TSK, + const TemplateArgumentList *TemplateArgs, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation POI, MemberSpecializationInfo *MSInfo); + + /// Retrieve the declaration of the function template specialization. + FunctionDecl *getFunction() const { return Function.getPointer(); } + /// Retrieve the template from which this function was specialized. FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } @@ -588,9 +609,44 @@ public: PointOfInstantiation = POI; } + /// Get the specialization info if this function template specialization is + /// also a member specialization: + /// + /// \code + /// template<typename> struct A { + /// template<typename> void f(); + /// template<> void f<int>(); // ClassScopeFunctionSpecializationDecl + /// }; + /// \endcode + /// + /// Here, A<int>::f<int> is a function template specialization that is + /// an explicit specialization of A<int>::f, but it's also a member + /// specialization (an implicit instantiation in this case) of A::f<int>. + /// Further: + /// + /// \code + /// template<> template<> void A<int>::f<int>() {} + /// \endcode + /// + /// ... declares a function template specialization that is an explicit + /// specialization of A<int>::f, and is also an explicit member + /// specialization of A::f<int>. + /// + /// Note that the TemplateSpecializationKind of the MemberSpecializationInfo + /// need not be the same as that returned by getTemplateSpecializationKind(), + /// and represents the relationship between the function and the class-scope + /// explicit specialization in the original templated class -- whereas our + /// TemplateSpecializationKind represents the relationship between the + /// function and the function template, and should always be + /// TSK_ExplicitSpecialization whenever we have MemberSpecializationInfo. + MemberSpecializationInfo *getMemberSpecializationInfo() const { + return numTrailingObjects(OverloadToken<MemberSpecializationInfo *>()) + ? getTrailingObjects<MemberSpecializationInfo *>()[0] + : nullptr; + } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->asArray(), - Function->getASTContext()); + Profile(ID, TemplateArguments->asArray(), getFunction()->getASTContext()); } static void @@ -956,7 +1012,7 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> { using DeclType = FunctionDecl; static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) { - return I->Function; + return I->getFunction(); } static ArrayRef<TemplateArgument> @@ -1747,6 +1803,20 @@ public: return getSpecializationKind() == TSK_ExplicitSpecialization; } + /// Is this an explicit specialization at class scope (within the class that + /// owns the primary template)? For example: + /// + /// \code + /// template<typename T> struct Outer { + /// template<typename U> struct Inner; + /// template<> struct Inner; // class-scope explicit specialization + /// }; + /// \endcode + bool isClassScopeExplicitSpecialization() const { + return isExplicitSpecialization() && + isa<CXXRecordDecl>(getLexicalDeclContext()); + } + /// True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. @@ -2395,8 +2465,6 @@ public: /// Declaration of a function specialization at template class scope. /// -/// This is a non-standard extension needed to support MSVC. -/// /// For example: /// \code /// template <class T> @@ -2409,17 +2477,18 @@ public: /// "template<> foo(int a)" will be saved in Specialization as a normal /// CXXMethodDecl. Then during an instantiation of class A, it will be /// transformed into an actual function specialization. +/// +/// FIXME: This is redundant; we could store the same information directly on +/// the CXXMethodDecl as a DependentFunctionTemplateSpecializationInfo. class ClassScopeFunctionSpecializationDecl : public Decl { CXXMethodDecl *Specialization; - bool HasExplicitTemplateArgs; - TemplateArgumentListInfo TemplateArgs; + const ASTTemplateArgumentListInfo *TemplateArgs; - ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, - CXXMethodDecl *FD, bool Args, - TemplateArgumentListInfo TemplArgs) + ClassScopeFunctionSpecializationDecl( + DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, + const ASTTemplateArgumentListInfo *TemplArgs) : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD), HasExplicitTemplateArgs(Args), - TemplateArgs(std::move(TemplArgs)) {} + Specialization(FD), TemplateArgs(TemplArgs) {} ClassScopeFunctionSpecializationDecl(EmptyShell Empty) : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} @@ -2431,17 +2500,20 @@ public: friend class ASTDeclWriter; CXXMethodDecl *getSpecialization() const { return Specialization; } - bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } - const TemplateArgumentListInfo& templateArgs() const { return TemplateArgs; } - - static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C, - DeclContext *DC, - SourceLocation Loc, - CXXMethodDecl *FD, - bool HasExplicitTemplateArgs, - TemplateArgumentListInfo TemplateArgs) { + bool hasExplicitTemplateArgs() const { return TemplateArgs; } + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return TemplateArgs; + } + + static ClassScopeFunctionSpecializationDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, + bool HasExplicitTemplateArgs, + const TemplateArgumentListInfo &TemplateArgs) { return new (C, DC) ClassScopeFunctionSpecializationDecl( - DC, Loc, FD, HasExplicitTemplateArgs, std::move(TemplateArgs)); + DC, Loc, FD, + HasExplicitTemplateArgs + ? ASTTemplateArgumentListInfo::Create(C, TemplateArgs) + : nullptr); } static ClassScopeFunctionSpecializationDecl * @@ -2582,6 +2654,11 @@ public: return getSpecializationKind() == TSK_ExplicitSpecialization; } + bool isClassScopeExplicitSpecialization() const { + return isExplicitSpecialization() && + isa<CXXRecordDecl>(getLexicalDeclContext()); + } + /// True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. |