aboutsummaryrefslogtreecommitdiff
path: root/include/clang/AST/DeclTemplate.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/AST/DeclTemplate.h')
-rw-r--r--include/clang/AST/DeclTemplate.h175
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.