12#ifndef LLVM_CLANG_SEMA_TEMPLATE_H
13#define LLVM_CLANG_SEMA_TEMPLATE_H
21#include "llvm/ADT/ArrayRef.h"
22#include "llvm/ADT/DenseMap.h"
23#include "llvm/ADT/PointerUnion.h"
24#include "llvm/ADT/SmallVector.h"
80 struct ArgumentListLevel {
81 llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
86 using ArgListsIterator = ContainerType::iterator;
87 using ConstArgListsIterator = ContainerType::const_iterator;
91 ContainerType TemplateArgumentLists;
95 unsigned NumRetainedOuterLevels = 0;
124 return TemplateArgumentLists.size() + NumRetainedOuterLevels;
130 return TemplateArgumentLists.size();
135 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
136 return TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size();
140 return NumRetainedOuterLevels;
146 if (OldDepth < NumRetainedOuterLevels)
149 return NumRetainedOuterLevels;
150 return OldDepth - TemplateArgumentLists.size();
155 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
157 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size());
158 return TemplateArgumentLists[
getNumLevels() - Depth - 1].Args[Index];
165 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
166 auto AD = TemplateArgumentLists[
getNumLevels() - Depth - 1]
167 .AssociatedDeclAndFinal;
168 return {AD.getPointer(), AD.getInt()};
178 if (Depth < NumRetainedOuterLevels)
182 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size())
185 return !(*this)(Depth, Index).isNull();
189 for (ArgumentListLevel ListLevel : TemplateArgumentLists)
199 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
201 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size());
203 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args[Index]) = Arg;
212 assert(!NumRetainedOuterLevels &&
213 "substituted args outside retained args?");
215 TemplateArgumentLists.push_back(
222 assert(!NumRetainedOuterLevels &&
223 "substituted args outside retained args?");
225 TemplateArgumentLists.push_back({{}, Args});
229 assert(!NumRetainedOuterLevels &&
230 "substituted args outside retained args?");
231 TemplateArgumentLists.push_back({});
238 bool Final =
false) {
239 assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
240 "Replacing in an empty list?");
242 if (!TemplateArgumentLists.empty()) {
243 TemplateArgumentLists[0].Args = Args;
246 --NumRetainedOuterLevels;
247 TemplateArgumentLists.push_back(
248 {{AssociatedDecl, Final}, Args});
252 assert((!TemplateArgumentLists.empty()) &&
"Replacing in an empty list?");
253 TemplateArgumentLists.back().AssociatedDeclAndFinal.setPointer(
255 TemplateArgumentLists.back().Args = Args;
262 ++NumRetainedOuterLevels;
265 NumRetainedOuterLevels +=
Num;
270 return TemplateArgumentLists.front().Args;
274 return TemplateArgumentLists.back().Args;
276 ArgListsIterator
begin() {
return TemplateArgumentLists.begin(); }
277 ConstArgListsIterator
begin()
const {
278 return TemplateArgumentLists.begin();
280 ArgListsIterator
end() {
return TemplateArgumentLists.end(); }
281 ConstArgListsIterator
end()
const {
return TemplateArgumentLists.end(); }
283 LLVM_DUMP_METHOD
void dump()
const {
288 llvm::errs() <<
"NumRetainedOuterLevels: " << NumRetainedOuterLevels
290 for (
unsigned Depth = NumRetainedOuterLevels; Depth <
getNumLevels();
292 llvm::errs() << Depth <<
": ";
293 printTemplateArgumentList(
295 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args, PP);
296 llvm::errs() <<
"\n";
326 operator TPOC()
const {
return Value; }
334 bool DeducedFromArrayBound =
false;
340 bool DeducedFromArrayBound =
false)
346 const llvm::APSInt &
Value,
348 bool DeducedFromArrayBound)
350 DeducedFromArrayBound(DeducedFromArrayBound) {}
359 DeducedFromArrayBound = Deduced;
379 using LocalDeclsMap =
380 llvm::SmallDenseMap<
const Decl *,
381 llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
401 LocalDeclsMap LocalDecls;
416 bool CombineWithOuterScope;
421 bool InstantiatingLambdaOrBlock =
false;
425 NamedDecl *PartiallySubstitutedPack =
nullptr;
434 unsigned NumArgsInPartiallySubstitutedPack;
438 bool InstantiatingLambdaOrBlock =
false)
439 : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
440 CombineWithOuterScope(CombineWithOuterScope),
441 InstantiatingLambdaOrBlock(InstantiatingLambdaOrBlock) {
442 SemaRef.CurrentInstantiationScope =
this;
460 for (
unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
461 delete ArgumentPacks[I];
463 SemaRef.CurrentInstantiationScope = Outer;
470 if (
this == Outermost)
return this;
479 newScope->Outer =
nullptr;
483 newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
484 newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
485 newScope->NumArgsInPartiallySubstitutedPack =
486 NumArgsInPartiallySubstitutedPack;
488 for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
490 const Decl *D = I->first;
491 llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
492 newScope->LocalDecls[D];
493 if (
auto *D2 = dyn_cast<Decl *>(I->second)) {
499 newScope->ArgumentPacks.push_back(NewPack);
503 SemaRef.CurrentInstantiationScope = oldScope;
526 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
532 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
553 unsigned NumExplicitArgs);
558 assert(PartiallySubstitutedPack &&
"No partially-substituted pack");
559 PartiallySubstitutedPack =
nullptr;
560 ArgsInPartiallySubstitutedPack =
nullptr;
561 NumArgsInPartiallySubstitutedPack = 0;
569 unsigned *NumExplicitArgs =
nullptr)
const;
579 :
public DeclVisitor<TemplateDeclInstantiator, Decl *>
588 bool EvaluateConstraints =
true;
596 OutOfLinePartialSpecs;
603 std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 1>
604 OutOfLineVarPartialSpecs;
609 : SemaRef(SemaRef), SubstIndex(SemaRef, SemaRef.ArgPackSubstIndex),
610 Owner(Owner), TemplateArgs(TemplateArgs) {}
613 EvaluateConstraints = B;
616 return EvaluateConstraints;
620#define DECL(DERIVED, BASE) \
621 Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
622#define ABSTRACT_DECL(DECL)
625#define OBJCCONTAINER(DERIVED, BASE)
626#define FILESCOPEASM(DERIVED, BASE)
627#define TOPLEVELSTMT(DERIVED, BASE)
628#define IMPORT(DERIVED, BASE)
629#define EXPORT(DERIVED, BASE)
630#define LINKAGESPEC(DERIVED, BASE)
631#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
632#define OBJCMETHOD(DERIVED, BASE)
633#define OBJCTYPEPARAM(DERIVED, BASE)
634#define OBJCIVAR(DERIVED, BASE)
635#define OBJCPROPERTY(DERIVED, BASE)
636#define OBJCPROPERTYIMPL(DERIVED, BASE)
637#define EMPTY(DERIVED, BASE)
638#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
641#define OUTLINEDFUNCTION(DERIVED, BASE)
644#define BLOCK(DERIVED, BASE)
645#define CAPTURED(DERIVED, BASE)
646#define IMPLICITPARAM(DERIVED, BASE)
648#include "clang/AST/DeclNodes.inc"
673 StartingScope = SemaRef.CurrentInstantiationScope;
679 StartingScope =
nullptr;
695 return OutOfLinePartialSpecs.begin();
699 return OutOfLineVarPartialSpecs.begin();
707 return OutOfLinePartialSpecs.end();
711 return OutOfLineVarPartialSpecs.end();
749 Decl *instantiateUnresolvedUsingDecl(
T *D,
750 bool InstantiatingPackElement =
false);
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Represents a C++ declaration that introduces decls from somewhere else.
A binding in a decomposition declaration.
Represents a static or instance method of a struct/union/class.
Declaration of a class template.
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
A simple visitor class that helps create declaration visitors.
Decl - This represents one declaration (or definition), e.g.
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Represents a ValueDecl that came out of a declarator.
void setDeducedFromArrayBound(bool Deduced)
Specify whether the given non-type template argument was deduced from an array bound.
DeducedTemplateArgument()=default
DeducedTemplateArgument(const TemplateArgument &Arg, bool DeducedFromArrayBound=false)
DeducedTemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType ValueType, bool DeducedFromArrayBound)
Construct an integral non-type template argument that has been deduced, possibly from an array bound.
bool wasDeducedFromArrayBound() const
For a non-type template argument, determine whether the template argument was deduced from an array b...
Represents a function declaration or definition.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A stack-allocated class that identifies which local variable declaration instantiations are present i...
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope=false, bool InstantiatingLambdaOrBlock=false)
LocalInstantiationScope & operator=(const LocalInstantiationScope &)=delete
LocalInstantiationScope(const LocalInstantiationScope &)=delete
void SetPartiallySubstitutedPack(NamedDecl *Pack, const TemplateArgument *ExplicitArgs, unsigned NumExplicitArgs)
Note that the given parameter pack has been partially substituted via explicit specification of templ...
NamedDecl * getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs=nullptr, unsigned *NumExplicitArgs=nullptr) const
Retrieve the partially-substitued template parameter pack.
void Exit()
Exit this local instantiation scope early.
bool isLocalPackExpansion(const Decl *D)
Determine whether D is a pack expansion created in this scope.
SmallVector< ValueDecl *, 4 > DeclArgumentPack
A set of declarations.
llvm::PointerUnion< Decl *, DeclArgumentPack * > * getInstantiationOfIfExists(const Decl *D)
Similar to findInstantiationOf(), but it wouldn't assert if the instantiation was not found within th...
~LocalInstantiationScope()
static void deleteScopes(LocalInstantiationScope *Scope, LocalInstantiationScope *Outermost)
deletes the given scope, and all outer scopes, down to the given outermost scope.
const Sema & getSema() const
void InstantiatedLocal(const Decl *D, Decl *Inst)
void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst)
void ResetPartiallySubstitutedPack()
Reset the partially-substituted pack when it is no longer of interest.
bool isLambdaOrBlock() const
Determine whether this scope is for instantiating a lambda or block.
void MakeInstantiatedLocalArgPack(const Decl *D)
LocalInstantiationScope * cloneScopes(LocalInstantiationScope *Outermost)
Clone this scope, and all outer scopes, down to the given outermost scope.
llvm::PointerUnion< Decl *, DeclArgumentPack * > * findInstantiationOf(const Decl *D)
Find the instantiation of the declaration D within the current instantiation scope.
Represents the results of name lookup.
Data structure that captures multiple levels of template argument lists for use in template instantia...
bool hasTemplateArgument(unsigned Depth, unsigned Index) const
Determine whether there is a non-NULL template argument at the given depth and index.
ConstArgListsIterator end() const
const ArgList & getInnermost() const
Retrieve the innermost template argument list.
unsigned getNumSubsitutedArgs(unsigned Depth) const
std::pair< Decl *, bool > getAssociatedDecl(unsigned Depth) const
A template-like entity which owns the whole pattern being substituted.
void addOuterRetainedLevel()
Add an outermost level that we are not substituting.
ConstArgListsIterator begin() const
LLVM_DUMP_METHOD void dump() const
MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final)
Construct a single-level template argument list.
TemplateSubstitutionKind getKind() const
Determine the kind of template substitution being performed.
void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final)
Add a new outmost level to the multi-level template argument list.
unsigned getNumLevels() const
Determine the number of levels in this template argument list.
void setKind(TemplateSubstitutionKind K)
unsigned getNumSubstitutedLevels() const
Determine the number of substituted levels in this template argument list.
const TemplateArgument & operator()(unsigned Depth, unsigned Index) const
Retrieve the template argument at a given depth and index.
void replaceOutermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
const ArgList & getOutermost() const
Retrieve the outermost template argument list.
void addOuterRetainedLevels(unsigned Num)
MultiLevelTemplateArgumentList()=default
Construct an empty set of template argument lists.
unsigned getNumRetainedOuterLevels() const
bool isAnyArgInstantiationDependent() const
unsigned getNewDepth(unsigned OldDepth) const
Determine how many of the OldDepth outermost template parameter lists would be removed by substitutin...
void setArgument(unsigned Depth, unsigned Index, TemplateArgument Arg)
Clear out a specific template argument.
void addOuterTemplateArguments(std::nullopt_t)
void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final=false)
Replaces the current 'innermost' level with the provided argument list.
void addOuterTemplateArguments(ArgList Args)
bool isRewrite() const
Determine whether we are rewriting template parameters rather than substituting for them.
This represents a decl that may have a name.
Represents a parameter to a function.
A (possibly-)qualified type.
Scope - A scope is a transient data structure that is used while parsing the program.
RAII object used to change the argument pack substitution index within a Sema object.
Sema - This implements semantic analysis and AST building for C.
SmallVector< LateInstantiatedAttribute, 1 > LateInstantiatedAttrVec
Represents the declaration of a struct/union/class/enum.
Represents a template argument.
bool isInstantiationDependent() const
Whether this template argument is dependent on a template parameter.
constexpr TemplateArgument()
Construct an empty, invalid template argument.
void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA)
void disableLateAttributeInstantiation()
SmallVectorImpl< std::pair< ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl * > >::iterator delayed_partial_spec_iterator
@ RewriteSpaceshipAsEqualEqual
delayed_var_partial_spec_iterator delayed_var_partial_spec_end()
delayed_partial_spec_iterator delayed_partial_spec_begin()
Return an iterator to the beginning of the set of "delayed" partial specializations,...
void setEvaluateConstraints(bool B)
Decl * VisitDecl(Decl *D)
TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs)
VarTemplateSpecializationDecl * VisitVarTemplateSpecializationDecl(VarTemplateDecl *VarTemplate, VarDecl *FromVar, ArrayRef< TemplateArgument > Converted, VarTemplateSpecializationDecl *PrevDecl=nullptr)
Decl * VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, ArrayRef< BindingDecl * > *Bindings=nullptr)
bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl)
Initializes common fields of an instantiated method declaration (New) from the corresponding fields o...
LocalInstantiationScope * getStartingScope() const
bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl)
Initializes the common fields of an instantiation function declaration (New) from the corresponding f...
VarTemplatePartialSpecializationDecl * InstantiateVarTemplatePartialSpecialization(VarTemplateDecl *VarTemplate, VarTemplatePartialSpecializationDecl *PartialSpec)
Instantiate the declaration of a variable template partial specialization.
void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T, TypeSourceInfo *&TInfo, DeclarationNameInfo &NameInfo)
TypeSourceInfo * SubstFunctionType(FunctionDecl *D, SmallVectorImpl< ParmVarDecl * > &Params)
void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern)
Decl * VisitFunctionDecl(FunctionDecl *D, TemplateParameterList *TemplateParams, RewriteKind RK=RewriteKind::None)
Normal class members are of more specific types and therefore don't make it here.
Decl * VisitCXXMethodDecl(CXXMethodDecl *D, TemplateParameterList *TemplateParams, RewriteKind RK=RewriteKind::None)
SmallVectorImpl< std::pair< VarTemplateDecl *, VarTemplatePartialSpecializationDecl * > >::iterator delayed_var_partial_spec_iterator
Decl * InstantiateTypeAliasTemplateDecl(TypeAliasTemplateDecl *D)
bool getEvaluateConstraints()
delayed_partial_spec_iterator delayed_partial_spec_end()
Return an iterator to the end of the set of "delayed" partial specializations, which must be passed t...
Decl * VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst, LookupResult *Lookup)
bool SubstQualifier(const DeclaratorDecl *OldDecl, DeclaratorDecl *NewDecl)
TemplateParameterList * SubstTemplateParams(TemplateParameterList *List)
Instantiates a nested template parameter list in the current instantiation context.
Decl * InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias)
delayed_var_partial_spec_iterator delayed_var_partial_spec_begin()
ClassTemplatePartialSpecializationDecl * InstantiateClassTemplatePartialSpecialization(ClassTemplateDecl *ClassTemplate, ClassTemplatePartialSpecializationDecl *PartialSpec)
Instantiate the declaration of a class template partial specialization.
bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl)
Stores a list of template parameters for a TemplateDecl and its derived classes.
TemplatePartialOrderingContext(TPOC Value)
Declaration of an alias template.
A container of type source information.
Base class for declarations which introduce a typedef-name.
Represents a variable declaration or definition.
Declaration of a variable template.
Represents a variable template specialization, which refers to a variable template with a given set o...
The JSON file list parser is used to communicate input to InstallAPI.
TemplateSubstitutionKind
The kind of template substitution being performed.
@ Rewrite
We are substituting template parameters for (typically) other template parameters in order to rewrite...
@ Specialization
We are substituting template parameters for template arguments in order to form a template specializa...
const FunctionProtoType * T
@ VarTemplate
The name was classified as a variable template name.
TPOC
The context in which partial ordering of function templates occurs.
@ TPOC_Conversion
Partial ordering of function templates for a call to a conversion function.
@ TPOC_Other
Partial ordering of function templates in other contexts, e.g., taking the address of a function temp...
@ TPOC_Call
Partial ordering of function templates for a function call.
U cast(CodeGen::Address addr)
@ Enum
The "enum" keyword introduces the elaborated-type-specifier.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...
Describes how types, statements, expressions, and declarations should be printed.