summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2019-05-02 00:49:14 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2019-05-02 00:49:14 +0000
commit672ad5280a92fdc73cf54e6fc6ec50e73f6aa7d3 (patch)
tree56d21195b68ef956a8c4264da03e75751877d732 /include
parent2d77937455e8f133a9e4df562d91f40a97c59c8c (diff)
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
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/ASTContext.h10
-rw-r--r--include/clang/AST/ASTNodeTraverser.h11
-rw-r--r--include/clang/AST/Decl.h18
-rw-r--r--include/clang/AST/DeclTemplate.h144
-rw-r--r--include/clang/AST/RecursiveASTVisitor.h6
-rw-r--r--include/clang/Sema/Template.h3
6 files changed, 125 insertions, 67 deletions
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<const VarDecl *, BlockVarCopyInit> BlockVarCopyInits;
- /// Mapping from class scope functions specialization to their
- /// template patterns.
- llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
- 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<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.
@@ -534,17 +518,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(); }
@@ -587,9 +604,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
@@ -955,7 +1007,7 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> {
using DeclType = FunctionDecl;
static DeclType *getDecl(FunctionTemplateSpecializationInfo *I) {
- return I->Function;
+ return I->getFunction();
}
static ArrayRef<TemplateArgument>
@@ -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 <class T>
@@ -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<const ASTTemplateArgumentListInfo *>
+ ClassScopeSpecializationArgs = llvm::None);
Decl *VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams);
Decl *VisitDecl(Decl *D);