aboutsummaryrefslogtreecommitdiff
path: root/clang/include/clang/Sema/Template.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang/include/clang/Sema/Template.h')
-rw-r--r--clang/include/clang/Sema/Template.h46
1 files changed, 46 insertions, 0 deletions
diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h
index 4c1cfecd4de6..91d175fdd050 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -42,6 +42,17 @@ class TypedefNameDecl;
class TypeSourceInfo;
class VarDecl;
+/// The kind of template substitution being performed.
+enum class TemplateSubstitutionKind : char {
+ /// We are substituting template parameters for template arguments in order
+ /// to form a template specialization.
+ Specialization,
+ /// We are substituting template parameters for (typically) other template
+ /// parameters in order to rewrite a declaration as a different declaration
+ /// (for example, when forming a deduction guide from a constructor).
+ Rewrite,
+};
+
/// Data structure that captures multiple levels of template argument
/// lists for use in template instantiation.
///
@@ -73,6 +84,9 @@ class VarDecl;
/// being substituted.
unsigned NumRetainedOuterLevels = 0;
+ /// The kind of substitution described by this argument list.
+ TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;
+
public:
/// Construct an empty set of template argument lists.
MultiLevelTemplateArgumentList() = default;
@@ -83,6 +97,18 @@ class VarDecl;
addOuterTemplateArguments(&TemplateArgs);
}
+ void setKind(TemplateSubstitutionKind K) { Kind = K; }
+
+ /// Determine the kind of template substitution being performed.
+ TemplateSubstitutionKind getKind() const { return Kind; }
+
+ /// Determine whether we are rewriting template parameters rather than
+ /// substituting for them. If so, we should not leave references to the
+ /// original template parameters behind.
+ bool isRewrite() const {
+ return Kind == TemplateSubstitutionKind::Rewrite;
+ }
+
/// Determine the number of levels in this template argument
/// list.
unsigned getNumLevels() const {
@@ -95,6 +121,20 @@ class VarDecl;
return TemplateArgumentLists.size();
}
+ unsigned getNumRetainedOuterLevels() const {
+ return NumRetainedOuterLevels;
+ }
+
+ /// Determine how many of the \p OldDepth outermost template parameter
+ /// lists would be removed by substituting these arguments.
+ unsigned getNewDepth(unsigned OldDepth) const {
+ if (OldDepth < NumRetainedOuterLevels)
+ return OldDepth;
+ if (OldDepth < getNumLevels())
+ return NumRetainedOuterLevels;
+ return OldDepth - TemplateArgumentLists.size();
+ }
+
/// Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
@@ -149,6 +189,9 @@ class VarDecl;
void addOuterRetainedLevel() {
++NumRetainedOuterLevels;
}
+ void addOuterRetainedLevels(unsigned Num) {
+ NumRetainedOuterLevels += Num;
+ }
/// Retrieve the innermost template argument list.
const ArgList &getInnermost() const {
@@ -412,6 +455,9 @@ class VarDecl;
NamedDecl *
getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
unsigned *NumExplicitArgs = nullptr) const;
+
+ /// Determine whether D is a pack expansion created in this scope.
+ bool isLocalPackExpansion(const Decl *D);
};
class TemplateDeclInstantiator