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;
100 bool RetainInnerDepths =
false;
130 return TemplateArgumentLists.size() + NumRetainedOuterLevels;
136 return TemplateArgumentLists.size();
141 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
142 return TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size();
146 return NumRetainedOuterLevels;
152 if (OldDepth < NumRetainedOuterLevels)
155 return NumRetainedOuterLevels;
156 return OldDepth - TemplateArgumentLists.size();
161 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
163 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size());
164 return TemplateArgumentLists[
getNumLevels() - Depth - 1].Args[Index];
171 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
172 auto AD = TemplateArgumentLists[
getNumLevels() - Depth - 1]
173 .AssociatedDeclAndFinal;
174 return {AD.getPointer(), AD.getInt()};
184 if (Depth < NumRetainedOuterLevels)
188 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size())
191 return !(*this)(Depth, Index).isNull();
195 for (ArgumentListLevel ListLevel : TemplateArgumentLists)
207 assert(NumRetainedOuterLevels <= Depth && Depth <
getNumLevels());
209 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args.size());
211 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args[Index]) = Arg;
220 assert(!NumRetainedOuterLevels &&
221 "substituted args outside retained args?");
223 TemplateArgumentLists.push_back(
230 assert(!NumRetainedOuterLevels &&
231 "substituted args outside retained args?");
233 TemplateArgumentLists.push_back({{}, Args});
237 assert(!NumRetainedOuterLevels &&
238 "substituted args outside retained args?");
239 TemplateArgumentLists.push_back({});
246 bool Final =
false) {
247 assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
248 "Replacing in an empty list?");
250 if (!TemplateArgumentLists.empty()) {
251 TemplateArgumentLists[0].Args = Args;
254 --NumRetainedOuterLevels;
255 TemplateArgumentLists.push_back(
256 {{AssociatedDecl, Final}, Args});
260 assert((!TemplateArgumentLists.empty()) &&
"Replacing in an empty list?");
261 TemplateArgumentLists.back().AssociatedDeclAndFinal.setPointer(
263 TemplateArgumentLists.back().Args = Args;
270 ++NumRetainedOuterLevels;
273 NumRetainedOuterLevels +=
Num;
278 return TemplateArgumentLists.front().Args;
282 return TemplateArgumentLists.back().Args;
284 ArgListsIterator
begin() {
return TemplateArgumentLists.begin(); }
285 ConstArgListsIterator
begin()
const {
286 return TemplateArgumentLists.begin();
288 ArgListsIterator
end() {
return TemplateArgumentLists.end(); }
289 ConstArgListsIterator
end()
const {
return TemplateArgumentLists.end(); }
291 LLVM_DUMP_METHOD
void dump()
const {
296 llvm::errs() <<
"NumRetainedOuterLevels: " << NumRetainedOuterLevels
298 for (
unsigned Depth = NumRetainedOuterLevels; Depth <
getNumLevels();
300 llvm::errs() << Depth <<
": ";
301 printTemplateArgumentList(
303 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args, PP);
304 llvm::errs() <<
"\n";
334 operator TPOC()
const {
return Value; }
342 bool DeducedFromArrayBound =
false;
348 bool DeducedFromArrayBound =
false)
354 const llvm::APSInt &
Value,
356 bool DeducedFromArrayBound)
358 DeducedFromArrayBound(DeducedFromArrayBound) {}
367 DeducedFromArrayBound =
Deduced;
387 using LocalDeclsMap =
388 llvm::SmallDenseMap<
const Decl *,
389 llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
409 LocalDeclsMap LocalDecls;
424 bool CombineWithOuterScope;
429 bool InstantiatingLambdaOrBlock =
false;
433 NamedDecl *PartiallySubstitutedPack =
nullptr;
442 unsigned NumArgsInPartiallySubstitutedPack;
446 bool InstantiatingLambdaOrBlock =
false)
447 : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
448 CombineWithOuterScope(CombineWithOuterScope),
449 InstantiatingLambdaOrBlock(InstantiatingLambdaOrBlock) {
450 SemaRef.CurrentInstantiationScope =
this;
468 for (
unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
469 delete ArgumentPacks[I];
471 SemaRef.CurrentInstantiationScope = Outer;
478 if (
this == Outermost)
return this;
487 newScope->Outer =
nullptr;
491 newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
492 newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
493 newScope->NumArgsInPartiallySubstitutedPack =
494 NumArgsInPartiallySubstitutedPack;
496 for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
498 const Decl *D = I->first;
499 llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
500 newScope->LocalDecls[D];
501 if (
auto *D2 = dyn_cast<Decl *>(I->second)) {
507 newScope->ArgumentPacks.push_back(NewPack);
511 SemaRef.CurrentInstantiationScope = oldScope;
534 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
540 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
561 unsigned NumExplicitArgs);
566 assert(PartiallySubstitutedPack &&
"No partially-substituted pack");
567 PartiallySubstitutedPack =
nullptr;
568 ArgsInPartiallySubstitutedPack =
nullptr;
569 NumArgsInPartiallySubstitutedPack = 0;
577 unsigned *NumExplicitArgs =
nullptr)
const;
587 :
public DeclVisitor<TemplateDeclInstantiator, Decl *>
596 bool EvaluateConstraints =
true;
604 OutOfLinePartialSpecs;
611 std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 1>
612 OutOfLineVarPartialSpecs;
617 : SemaRef(SemaRef), SubstIndex(SemaRef, SemaRef.ArgPackSubstIndex),
618 Owner(Owner), TemplateArgs(TemplateArgs) {}
621 EvaluateConstraints = B;
624 return EvaluateConstraints;
628#define DECL(DERIVED, BASE) \
629 Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
630#define ABSTRACT_DECL(DECL)
633#define OBJCCONTAINER(DERIVED, BASE)
634#define FILESCOPEASM(DERIVED, BASE)
635#define TOPLEVELSTMT(DERIVED, BASE)
636#define IMPORT(DERIVED, BASE)
637#define EXPORT(DERIVED, BASE)
638#define LINKAGESPEC(DERIVED, BASE)
639#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
640#define OBJCMETHOD(DERIVED, BASE)
641#define OBJCTYPEPARAM(DERIVED, BASE)
642#define OBJCIVAR(DERIVED, BASE)
643#define OBJCPROPERTY(DERIVED, BASE)
644#define OBJCPROPERTYIMPL(DERIVED, BASE)
645#define EMPTY(DERIVED, BASE)
646#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
649#define OUTLINEDFUNCTION(DERIVED, BASE)
652#define BLOCK(DERIVED, BASE)
653#define CAPTURED(DERIVED, BASE)
654#define IMPLICITPARAM(DERIVED, BASE)
656#include "clang/AST/DeclNodes.inc"
681 StartingScope = SemaRef.CurrentInstantiationScope;
687 StartingScope =
nullptr;
703 return OutOfLinePartialSpecs.begin();
707 return OutOfLineVarPartialSpecs.begin();
715 return OutOfLinePartialSpecs.end();
719 return OutOfLineVarPartialSpecs.end();
757 Decl *instantiateUnresolvedUsingDecl(T *D,
758 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
bool retainInnerDepths() 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 setRetainInnerDepths()
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.
bool isNull() const
Determine whether this template argument has no value.
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...
@ VarTemplate
The name was classified as a variable template name.
@ Deduced
The normal deduced case.
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.