aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/include/clang/Sema/Template.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/include/clang/Sema/Template.h')
-rw-r--r--contrib/llvm-project/clang/include/clang/Sema/Template.h147
1 files changed, 125 insertions, 22 deletions
diff --git a/contrib/llvm-project/clang/include/clang/Sema/Template.h b/contrib/llvm-project/clang/include/clang/Sema/Template.h
index 540d2c9aa87e..ce44aca797b0 100644
--- a/contrib/llvm-project/clang/include/clang/Sema/Template.h
+++ b/contrib/llvm-project/clang/include/clang/Sema/Template.h
@@ -23,6 +23,7 @@
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SmallVector.h"
#include <cassert>
+#include <optional>
#include <utility>
namespace clang {
@@ -74,11 +75,20 @@ enum class TemplateSubstitutionKind : char {
/// template argument list (17) at depth 1.
class MultiLevelTemplateArgumentList {
/// The template argument list at a certain template depth
+
using ArgList = ArrayRef<TemplateArgument>;
+ struct ArgumentListLevel {
+ llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
+ ArgList Args;
+ };
+ using ContainerType = SmallVector<ArgumentListLevel, 4>;
+
+ using ArgListsIterator = ContainerType::iterator;
+ using ConstArgListsIterator = ContainerType::const_iterator;
/// The template argument lists, stored from the innermost template
/// argument list (first) to the outermost template argument list (last).
- SmallVector<ArgList, 4> TemplateArgumentLists;
+ ContainerType TemplateArgumentLists;
/// The number of outer levels of template arguments that are not
/// being substituted.
@@ -92,9 +102,8 @@ enum class TemplateSubstitutionKind : char {
MultiLevelTemplateArgumentList() = default;
/// Construct a single-level template argument list.
- explicit
- MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) {
- addOuterTemplateArguments(&TemplateArgs);
+ MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
+ addOuterTemplateArguments(D, Args, Final);
}
void setKind(TemplateSubstitutionKind K) { Kind = K; }
@@ -121,6 +130,12 @@ enum class TemplateSubstitutionKind : char {
return TemplateArgumentLists.size();
}
+ // Determine the number of substituted args at 'Depth'.
+ unsigned getNumSubsitutedArgs(unsigned Depth) const {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
+ }
+
unsigned getNumRetainedOuterLevels() const {
return NumRetainedOuterLevels;
}
@@ -138,8 +153,19 @@ enum class TemplateSubstitutionKind : char {
/// Retrieve the template argument at a given depth and index.
const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
- assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
- return TemplateArgumentLists[getNumLevels() - Depth - 1][Index];
+ assert(Index <
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
+ return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
+ }
+
+ /// A template-like entity which owns the whole pattern being substituted.
+ /// This will usually own a set of template parameters, or in some
+ /// cases might even be a template parameter itself.
+ std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
+ assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+ auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
+ .AssociatedDeclAndFinal;
+ return {AD.getPointer(), AD.getInt()};
}
/// Determine whether there is a non-NULL template argument at the
@@ -152,35 +178,77 @@ enum class TemplateSubstitutionKind : char {
if (Depth < NumRetainedOuterLevels)
return false;
- if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size())
+ if (Index >=
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
return false;
return !(*this)(Depth, Index).isNull();
}
+ bool isAnyArgInstantiationDependent() const {
+ for (ArgumentListLevel ListLevel : TemplateArgumentLists)
+ for (const TemplateArgument &TA : ListLevel.Args)
+ if (TA.isInstantiationDependent())
+ return true;
+ return false;
+ }
+
/// Clear out a specific template argument.
void setArgument(unsigned Depth, unsigned Index,
TemplateArgument Arg) {
assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
- assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size());
- const_cast<TemplateArgument&>(
- TemplateArgumentLists[getNumLevels() - Depth - 1][Index])
- = Arg;
+ assert(Index <
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
+ const_cast<TemplateArgument &>(
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
}
- /// Add a new outermost level to the multi-level template argument
+ /// Add a new outmost level to the multi-level template argument
/// list.
- void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) {
- addOuterTemplateArguments(ArgList(TemplateArgs->data(),
- TemplateArgs->size()));
+ /// A 'Final' substitution means that Subst* nodes won't be built
+ /// for the replacements.
+ void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
+ bool Final) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ assert(getKind() == TemplateSubstitutionKind::Specialization);
+ TemplateArgumentLists.push_back(
+ {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
+ Final},
+ Args});
}
- /// Add a new outmost level to the multi-level template argument
- /// list.
void addOuterTemplateArguments(ArgList Args) {
assert(!NumRetainedOuterLevels &&
"substituted args outside retained args?");
- TemplateArgumentLists.push_back(Args);
+ assert(getKind() == TemplateSubstitutionKind::Rewrite);
+ TemplateArgumentLists.push_back({{}, Args});
+ }
+
+ void addOuterTemplateArguments(std::nullopt_t) {
+ assert(!NumRetainedOuterLevels &&
+ "substituted args outside retained args?");
+ TemplateArgumentLists.push_back({});
+ }
+
+ /// Replaces the current 'innermost' level with the provided argument list.
+ /// This is useful for type deduction cases where we need to get the entire
+ /// list from the AST, but then add the deduced innermost list.
+ void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
+ assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
+ "Replacing in an empty list?");
+
+ if (!TemplateArgumentLists.empty()) {
+ assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
+ TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
+ AssociatedDecl) &&
+ "Trying to change incorrect declaration?");
+ TemplateArgumentLists[0].Args = Args;
+ } else {
+ --NumRetainedOuterLevels;
+ TemplateArgumentLists.push_back(
+ {{AssociatedDecl, /*Final=*/false}, Args});
+ }
}
/// Add an outermost level that we are not substituting. We have no
@@ -195,7 +263,34 @@ enum class TemplateSubstitutionKind : char {
/// Retrieve the innermost template argument list.
const ArgList &getInnermost() const {
- return TemplateArgumentLists.front();
+ return TemplateArgumentLists.front().Args;
+ }
+ /// Retrieve the outermost template argument list.
+ const ArgList &getOutermost() const {
+ return TemplateArgumentLists.back().Args;
+ }
+ ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
+ ConstArgListsIterator begin() const {
+ return TemplateArgumentLists.begin();
+ }
+ ArgListsIterator end() { return TemplateArgumentLists.end(); }
+ ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+ LLVM_DUMP_METHOD void dump() const {
+ LangOptions LO;
+ LO.CPlusPlus = true;
+ LO.Bool = true;
+ PrintingPolicy PP(LO);
+ llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
+ << "\n";
+ for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
+ ++Depth) {
+ llvm::errs() << Depth << ": ";
+ printTemplateArgumentList(
+ llvm::errs(),
+ TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
+ llvm::errs() << "\n";
+ }
}
};
@@ -398,7 +493,7 @@ enum class TemplateSubstitutionKind : char {
return newScope;
}
- /// deletes the given scope, and all otuer scopes, down to the
+ /// deletes the given scope, and all outer scopes, down to the
/// given outermost scope.
static void deleteScopes(LocalInstantiationScope *Scope,
LocalInstantiationScope *Outermost) {
@@ -469,6 +564,8 @@ enum class TemplateSubstitutionKind : char {
const MultiLevelTemplateArgumentList &TemplateArgs;
Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
LocalInstantiationScope *StartingScope = nullptr;
+ // Whether to evaluate the C++20 constraints or simply substitute into them.
+ bool EvaluateConstraints = true;
/// A list of out-of-line class template partial
/// specializations that will need to be instantiated after the
@@ -492,6 +589,13 @@ enum class TemplateSubstitutionKind : char {
SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
Owner(Owner), TemplateArgs(TemplateArgs) {}
+ void setEvaluateConstraints(bool B) {
+ EvaluateConstraints = B;
+ }
+ bool getEvaluateConstraints() {
+ return EvaluateConstraints;
+ }
+
// Define all the decl visitors using DeclNodes.inc
#define DECL(DERIVED, BASE) \
Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
@@ -500,6 +604,7 @@ enum class TemplateSubstitutionKind : char {
// Decls which never appear inside a class or function.
#define OBJCCONTAINER(DERIVED, BASE)
#define FILESCOPEASM(DERIVED, BASE)
+#define TOPLEVELSTMT(DERIVED, BASE)
#define IMPORT(DERIVED, BASE)
#define EXPORT(DERIVED, BASE)
#define LINKAGESPEC(DERIVED, BASE)
@@ -528,8 +633,6 @@ enum class TemplateSubstitutionKind : char {
// A few supplemental visitor functions.
Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
TemplateParameterList *TemplateParams,
- Optional<const ASTTemplateArgumentListInfo *>
- ClassScopeSpecializationArgs = llvm::None,
RewriteKind RK = RewriteKind::None);
Decl *VisitFunctionDecl(FunctionDecl *D,
TemplateParameterList *TemplateParams,