From 672ad5280a92fdc73cf54e6fc6ec50e73f6aa7d3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Thu, 2 May 2019 00:49:14 +0000 Subject: Replace ad-hoc tracking of pattern for an instantiated class-scope explicit function specialization with the MemberSpecializationInfo used everywhere else. Not NFC: the ad-hoc pattern tracking was not being serialized / deserialized properly. That's fixed here. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359747 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/ASTContext.h | 10 --- include/clang/AST/ASTNodeTraverser.h | 11 ++- include/clang/AST/Decl.h | 18 +++- include/clang/AST/DeclTemplate.h | 144 ++++++++++++++++++++++---------- include/clang/AST/RecursiveASTVisitor.h | 6 +- include/clang/Sema/Template.h | 3 +- 6 files changed, 125 insertions(+), 67 deletions(-) (limited to 'include') diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 33f222c2e5..1cddb6fd29 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -265,11 +265,6 @@ private: /// Mapping from __block VarDecls to BlockVarCopyInit. llvm::DenseMap BlockVarCopyInits; - /// Mapping from class scope functions specialization to their - /// template patterns. - llvm::DenseMap - ClassScopeSpecializationPattern; - /// Mapping from materialized temporaries with static storage duration /// that appear in constant initializers to their evaluated values. These are /// allocated in a std::map because their address must be stable. @@ -891,11 +886,6 @@ public: TemplateOrSpecializationInfo getTemplateOrSpecializationInfo(const VarDecl *Var); - FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD); - - void setClassScopeSpecializationPattern(FunctionDecl *FD, - FunctionDecl *Pattern); - /// Note that the static data member \p Inst is an instantiation of /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, diff --git a/include/clang/AST/ASTNodeTraverser.h b/include/clang/AST/ASTNodeTraverser.h index 6268df8036..220c763d6e 100644 --- a/include/clang/AST/ASTNodeTraverser.h +++ b/include/clang/AST/ASTNodeTraverser.h @@ -221,8 +221,12 @@ public: Visit(TP); } - void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI) { - for (const auto &TA : TALI.arguments()) + void + dumpASTTemplateArgumentListInfo(const ASTTemplateArgumentListInfo *TALI) { + if (!TALI) + return; + + for (const auto &TA : TALI->arguments()) dumpTemplateArgumentLoc(TA); } @@ -465,8 +469,7 @@ public: void VisitClassScopeFunctionSpecializationDecl( const ClassScopeFunctionSpecializationDecl *D) { Visit(D->getSpecialization()); - if (D->hasExplicitTemplateArgs()) - dumpTemplateArgumentListInfo(D->templateArgs()); + dumpASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); } void VisitVarTemplateDecl(const VarTemplateDecl *D) { dumpTemplateDecl(D); } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index dc7d5657e9..507ca73fcb 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1742,10 +1742,19 @@ class FunctionDecl : public DeclaratorDecl, public: /// The kind of templated function a FunctionDecl can be. enum TemplatedKind { + // Not templated. TK_NonTemplate, + // The pattern in a function template declaration. TK_FunctionTemplate, + // A non-template function that is an instantiation or explicit + // specialization of a member of a templated class. TK_MemberSpecialization, + // An instantiation or explicit specialization of a function template. + // Note: this might have been instantiated from a templated class if it + // is a class-scope explicit specialization. TK_FunctionTemplateSpecialization, + // A function template specialization that hasn't yet been resolved to a + // particular specialized function template. TK_DependentFunctionTemplateSpecialization }; @@ -2440,10 +2449,6 @@ public: return getPrimaryTemplate() != nullptr; } - /// Retrieve the class scope template pattern that this function - /// template specialization is instantiated from. - FunctionDecl *getClassScopeSpecializationPattern() const; - /// If this function is actually a function template specialization, /// retrieve information about this function template specialization. /// Otherwise, returns NULL. @@ -2530,6 +2535,11 @@ public: /// represents. TemplateSpecializationKind getTemplateSpecializationKind() const; + /// Determine the kind of template specialization this function represents + /// for the purpose of template instantiation. + TemplateSpecializationKind + getTemplateSpecializationKindForInstantiation() const; + /// Determine what kind of template instantiation this function /// represents. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 3ac3f37469..a6d9e3904e 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -504,29 +504,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 { + /// The function template specialization that this structure describes and a + /// flag indicating if the function is a member specialization. + llvm::PointerIntPair Function; /// The function template from which this function template /// specialization was generated. @@ -534,17 +518,50 @@ public: /// The two bits contain the top 4 values of TemplateSpecializationKind. llvm::PointerIntPair 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()[0] = MSInfo; + } + + size_t numTrailingObjects(OverloadToken) 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(); } @@ -587,9 +604,44 @@ public: PointOfInstantiation = POI; } + /// Get the specialization info if this function template specialization is + /// also a member specialization: + /// + /// \code + /// template struct A { + /// template void f(); + /// template<> void f(); // ClassScopeFunctionSpecializationDecl + /// }; + /// \endcode + /// + /// Here, A::f is a function template specialization that is + /// an explicit specialization of A::f, but it's also a member + /// specialization (an implicit instantiation in this case) of A::f. + /// Further: + /// + /// \code + /// template<> template<> void A::f() {} + /// \endcode + /// + /// ... declares a function template specialization that is an explicit + /// specialization of A::f, and is also an explicit member + /// specialization of A::f. + /// + /// 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()) + ? getTrailingObjects()[0] + : nullptr; + } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, TemplateArguments->asArray(), - Function->getASTContext()); + Profile(ID, TemplateArguments->asArray(), getFunction()->getASTContext()); } static void @@ -955,7 +1007,7 @@ SpecEntryTraits { using DeclType = FunctionDecl; static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) { - return I->Function; + return I->getFunction(); } static ArrayRef @@ -2408,8 +2460,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 @@ -2422,17 +2472,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) {} @@ -2444,17 +2495,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 * diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 719f2bc4b9..22ef332dbb 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1458,9 +1458,9 @@ DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, { TRY_TO(TraverseDecl(D->getSpecialization())); if (D->hasExplicitTemplateArgs()) { - const TemplateArgumentListInfo &args = D->templateArgs(); - TRY_TO(TraverseTemplateArgumentLocsHelper(args.getArgumentArray(), - args.size())); + TRY_TO(TraverseTemplateArgumentLocsHelper( + D->getTemplateArgsAsWritten()->getTemplateArgs(), + D->getTemplateArgsAsWritten()->NumTemplateArgs)); } }) diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index b2f0fbb9ba..61de93449e 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -475,7 +475,8 @@ class VarDecl; // A few supplemental visitor functions. Decl *VisitCXXMethodDecl(CXXMethodDecl *D, TemplateParameterList *TemplateParams, - bool IsClassScopeSpecialization = false); + Optional + ClassScopeSpecializationArgs = llvm::None); Decl *VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams); Decl *VisitDecl(Decl *D); -- cgit v1.2.3