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;
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 assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
239 "Replacing in an empty list?");
241 if (!TemplateArgumentLists.empty()) {
242 assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
243 TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
245 "Trying to change incorrect declaration?");
246 TemplateArgumentLists[0].Args = Args;
248 --NumRetainedOuterLevels;
249 TemplateArgumentLists.push_back(
250 {{AssociatedDecl,
false}, Args});
258 ++NumRetainedOuterLevels;
261 NumRetainedOuterLevels += Num;
266 return TemplateArgumentLists.front().Args;
270 return TemplateArgumentLists.back().Args;
272 ArgListsIterator
begin() {
return TemplateArgumentLists.begin(); }
273 ConstArgListsIterator
begin()
const {
274 return TemplateArgumentLists.begin();
276 ArgListsIterator
end() {
return TemplateArgumentLists.end(); }
277 ConstArgListsIterator
end()
const {
return TemplateArgumentLists.end(); }
279 LLVM_DUMP_METHOD
void dump()
const {
284 llvm::errs() <<
"NumRetainedOuterLevels: " << NumRetainedOuterLevels
286 for (
unsigned Depth = NumRetainedOuterLevels; Depth <
getNumLevels();
288 llvm::errs() << Depth <<
": ";
291 TemplateArgumentLists[
getNumLevels() - Depth - 1].Args, PP);
292 llvm::errs() <<
"\n";
330 bool DeducedFromArrayBound =
false;
336 bool DeducedFromArrayBound =
false)
342 const llvm::APSInt &
Value,
344 bool DeducedFromArrayBound)
346 DeducedFromArrayBound(DeducedFromArrayBound) {}
355 DeducedFromArrayBound = Deduced;
375 using LocalDeclsMap =
376 llvm::SmallDenseMap<
const Decl *,
377 llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
397 LocalDeclsMap LocalDecls;
412 bool CombineWithOuterScope;
416 NamedDecl *PartiallySubstitutedPack =
nullptr;
425 unsigned NumArgsInPartiallySubstitutedPack;
429 : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
430 CombineWithOuterScope(CombineWithOuterScope) {
449 for (
unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
450 delete ArgumentPacks[I];
459 if (
this == Outermost)
return this;
468 newScope->Outer =
nullptr;
472 newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
473 newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
474 newScope->NumArgsInPartiallySubstitutedPack =
475 NumArgsInPartiallySubstitutedPack;
477 for (LocalDeclsMap::iterator I = LocalDecls.begin(),
E = LocalDecls.end();
479 const Decl *
D = I->first;
480 llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
481 newScope->LocalDecls[
D];
482 if (I->second.is<
Decl *>()) {
483 Stored = I->second.get<
Decl *>();
488 newScope->ArgumentPacks.push_back(NewPack);
515 llvm::PointerUnion<Decl *, DeclArgumentPack *> *
536 unsigned NumExplicitArgs);
541 assert(PartiallySubstitutedPack &&
"No partially-substituted pack");
542 PartiallySubstitutedPack =
nullptr;
543 ArgsInPartiallySubstitutedPack =
nullptr;
544 NumArgsInPartiallySubstitutedPack = 0;
552 unsigned *NumExplicitArgs =
nullptr)
const;
559 :
public DeclVisitor<TemplateDeclInstantiator, Decl *>
568 bool EvaluateConstraints =
true;
575 OutOfLinePartialSpecs;
582 std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
583 OutOfLineVarPartialSpecs;
589 SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
590 Owner(Owner), TemplateArgs(TemplateArgs) {}
593 EvaluateConstraints = B;
596 return EvaluateConstraints;
600#define DECL(DERIVED, BASE) \
601 Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
602#define ABSTRACT_DECL(DECL)
605#define OBJCCONTAINER(DERIVED, BASE)
606#define FILESCOPEASM(DERIVED, BASE)
607#define TOPLEVELSTMT(DERIVED, BASE)
608#define IMPORT(DERIVED, BASE)
609#define EXPORT(DERIVED, BASE)
610#define LINKAGESPEC(DERIVED, BASE)
611#define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
612#define OBJCMETHOD(DERIVED, BASE)
613#define OBJCTYPEPARAM(DERIVED, BASE)
614#define OBJCIVAR(DERIVED, BASE)
615#define OBJCPROPERTY(DERIVED, BASE)
616#define OBJCPROPERTYIMPL(DERIVED, BASE)
617#define EMPTY(DERIVED, BASE)
618#define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
621#define BLOCK(DERIVED, BASE)
622#define CAPTURED(DERIVED, BASE)
623#define IMPLICITPARAM(DERIVED, BASE)
625#include "clang/AST/DeclNodes.inc"
656 StartingScope =
nullptr;
672 return OutOfLinePartialSpecs.begin();
676 return OutOfLineVarPartialSpecs.begin();
684 return OutOfLinePartialSpecs.end();
688 return OutOfLineVarPartialSpecs.end();
727 Decl *instantiateUnresolvedUsingDecl(
T *
D,
728 bool InstantiatingPackElement =
false);
Defines the C++ template declaration subclasses.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
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.
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.
Captures a template argument whose value has been deduced via c++ template argument deduction.
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 & 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.
SmallVector< VarDecl *, 4 > DeclArgumentPack
A set of declarations.
bool isLocalPackExpansion(const Decl *D)
Determine whether D is a pack expansion created in this scope.
~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.
LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope=false)
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)
void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args)
Replaces the current 'innermost' level with the provided argument list.
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.
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 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.
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.
LocalInstantiationScope * CurrentInstantiationScope
The current instantiation scope used to store local variables.
Represents the declaration of a struct/union/class/enum.
A convenient class for passing around template argument information.
Represents a template argument.
bool isInstantiationDependent() const
Whether this template argument is dependent on a template parameter.
void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA)
void disableLateAttributeInstantiation()
@ 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)
SmallVectorImpl< std::pair< VarTemplateDecl *, VarTemplatePartialSpecializationDecl * > >::iterator delayed_var_partial_spec_iterator
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)
SmallVectorImpl< std::pair< ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl * > >::iterator delayed_partial_spec_iterator
Decl * VisitVarTemplateSpecializationDecl(VarTemplateDecl *VarTemplate, VarDecl *FromVar, const TemplateArgumentListInfo &TemplateArgsInfo, ArrayRef< TemplateArgument > Converted, VarTemplateSpecializationDecl *PrevDecl=nullptr)
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)
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...
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
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
void printTemplateArgumentList(raw_ostream &OS, ArrayRef< TemplateArgument > Args, const PrintingPolicy &Policy, const TemplateParameterList *TPL=nullptr)
Print a template argument list, including the '<' and '>' enclosing the template arguments.
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.
@ 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.