106f32e7eSjoerg //===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===// 206f32e7eSjoerg // 306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information. 506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 606f32e7eSjoerg //===----------------------------------------------------------------------===// 706f32e7eSjoerg // 806f32e7eSjoerg // This file provides types used in the semantic analysis of C++ templates. 906f32e7eSjoerg // 1006f32e7eSjoerg //===----------------------------------------------------------------------===// 1106f32e7eSjoerg 1206f32e7eSjoerg #ifndef LLVM_CLANG_SEMA_TEMPLATE_H 1306f32e7eSjoerg #define LLVM_CLANG_SEMA_TEMPLATE_H 1406f32e7eSjoerg 1506f32e7eSjoerg #include "clang/AST/DeclTemplate.h" 1606f32e7eSjoerg #include "clang/AST/DeclVisitor.h" 1706f32e7eSjoerg #include "clang/AST/TemplateBase.h" 1806f32e7eSjoerg #include "clang/AST/Type.h" 1906f32e7eSjoerg #include "clang/Basic/LLVM.h" 2006f32e7eSjoerg #include "clang/Sema/Sema.h" 2106f32e7eSjoerg #include "llvm/ADT/ArrayRef.h" 2206f32e7eSjoerg #include "llvm/ADT/DenseMap.h" 2306f32e7eSjoerg #include "llvm/ADT/PointerUnion.h" 2406f32e7eSjoerg #include "llvm/ADT/SmallVector.h" 2506f32e7eSjoerg #include <cassert> 2606f32e7eSjoerg #include <utility> 2706f32e7eSjoerg 2806f32e7eSjoerg namespace clang { 2906f32e7eSjoerg 3006f32e7eSjoerg class ASTContext; 3106f32e7eSjoerg class BindingDecl; 3206f32e7eSjoerg class CXXMethodDecl; 3306f32e7eSjoerg class Decl; 3406f32e7eSjoerg class DeclaratorDecl; 3506f32e7eSjoerg class DeclContext; 3606f32e7eSjoerg class EnumDecl; 3706f32e7eSjoerg class FunctionDecl; 3806f32e7eSjoerg class NamedDecl; 3906f32e7eSjoerg class ParmVarDecl; 4006f32e7eSjoerg class TagDecl; 4106f32e7eSjoerg class TypedefNameDecl; 4206f32e7eSjoerg class TypeSourceInfo; 4306f32e7eSjoerg class VarDecl; 4406f32e7eSjoerg 45*13fbcb42Sjoerg /// The kind of template substitution being performed. 46*13fbcb42Sjoerg enum class TemplateSubstitutionKind : char { 47*13fbcb42Sjoerg /// We are substituting template parameters for template arguments in order 48*13fbcb42Sjoerg /// to form a template specialization. 49*13fbcb42Sjoerg Specialization, 50*13fbcb42Sjoerg /// We are substituting template parameters for (typically) other template 51*13fbcb42Sjoerg /// parameters in order to rewrite a declaration as a different declaration 52*13fbcb42Sjoerg /// (for example, when forming a deduction guide from a constructor). 53*13fbcb42Sjoerg Rewrite, 54*13fbcb42Sjoerg }; 55*13fbcb42Sjoerg 5606f32e7eSjoerg /// Data structure that captures multiple levels of template argument 5706f32e7eSjoerg /// lists for use in template instantiation. 5806f32e7eSjoerg /// 5906f32e7eSjoerg /// Multiple levels of template arguments occur when instantiating the 6006f32e7eSjoerg /// definitions of member templates. For example: 6106f32e7eSjoerg /// 6206f32e7eSjoerg /// \code 6306f32e7eSjoerg /// template<typename T> 6406f32e7eSjoerg /// struct X { 6506f32e7eSjoerg /// template<T Value> 6606f32e7eSjoerg /// struct Y { 6706f32e7eSjoerg /// void f(); 6806f32e7eSjoerg /// }; 6906f32e7eSjoerg /// }; 7006f32e7eSjoerg /// \endcode 7106f32e7eSjoerg /// 7206f32e7eSjoerg /// When instantiating X<int>::Y<17>::f, the multi-level template argument 7306f32e7eSjoerg /// list will contain a template argument list (int) at depth 0 and a 7406f32e7eSjoerg /// template argument list (17) at depth 1. 7506f32e7eSjoerg class MultiLevelTemplateArgumentList { 7606f32e7eSjoerg /// The template argument list at a certain template depth 7706f32e7eSjoerg using ArgList = ArrayRef<TemplateArgument>; 7806f32e7eSjoerg 7906f32e7eSjoerg /// The template argument lists, stored from the innermost template 8006f32e7eSjoerg /// argument list (first) to the outermost template argument list (last). 8106f32e7eSjoerg SmallVector<ArgList, 4> TemplateArgumentLists; 8206f32e7eSjoerg 8306f32e7eSjoerg /// The number of outer levels of template arguments that are not 8406f32e7eSjoerg /// being substituted. 8506f32e7eSjoerg unsigned NumRetainedOuterLevels = 0; 8606f32e7eSjoerg 87*13fbcb42Sjoerg /// The kind of substitution described by this argument list. 88*13fbcb42Sjoerg TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization; 89*13fbcb42Sjoerg 9006f32e7eSjoerg public: 9106f32e7eSjoerg /// Construct an empty set of template argument lists. 9206f32e7eSjoerg MultiLevelTemplateArgumentList() = default; 9306f32e7eSjoerg 9406f32e7eSjoerg /// Construct a single-level template argument list. 9506f32e7eSjoerg explicit MultiLevelTemplateArgumentList(const TemplateArgumentList & TemplateArgs)9606f32e7eSjoerg MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { 9706f32e7eSjoerg addOuterTemplateArguments(&TemplateArgs); 9806f32e7eSjoerg } 9906f32e7eSjoerg setKind(TemplateSubstitutionKind K)100*13fbcb42Sjoerg void setKind(TemplateSubstitutionKind K) { Kind = K; } 101*13fbcb42Sjoerg 102*13fbcb42Sjoerg /// Determine the kind of template substitution being performed. getKind()103*13fbcb42Sjoerg TemplateSubstitutionKind getKind() const { return Kind; } 104*13fbcb42Sjoerg 105*13fbcb42Sjoerg /// Determine whether we are rewriting template parameters rather than 106*13fbcb42Sjoerg /// substituting for them. If so, we should not leave references to the 107*13fbcb42Sjoerg /// original template parameters behind. isRewrite()108*13fbcb42Sjoerg bool isRewrite() const { 109*13fbcb42Sjoerg return Kind == TemplateSubstitutionKind::Rewrite; 110*13fbcb42Sjoerg } 111*13fbcb42Sjoerg 11206f32e7eSjoerg /// Determine the number of levels in this template argument 11306f32e7eSjoerg /// list. getNumLevels()11406f32e7eSjoerg unsigned getNumLevels() const { 11506f32e7eSjoerg return TemplateArgumentLists.size() + NumRetainedOuterLevels; 11606f32e7eSjoerg } 11706f32e7eSjoerg 11806f32e7eSjoerg /// Determine the number of substituted levels in this template 11906f32e7eSjoerg /// argument list. getNumSubstitutedLevels()12006f32e7eSjoerg unsigned getNumSubstitutedLevels() const { 12106f32e7eSjoerg return TemplateArgumentLists.size(); 12206f32e7eSjoerg } 12306f32e7eSjoerg getNumRetainedOuterLevels()124*13fbcb42Sjoerg unsigned getNumRetainedOuterLevels() const { 125*13fbcb42Sjoerg return NumRetainedOuterLevels; 126*13fbcb42Sjoerg } 127*13fbcb42Sjoerg 128*13fbcb42Sjoerg /// Determine how many of the \p OldDepth outermost template parameter 129*13fbcb42Sjoerg /// lists would be removed by substituting these arguments. getNewDepth(unsigned OldDepth)130*13fbcb42Sjoerg unsigned getNewDepth(unsigned OldDepth) const { 131*13fbcb42Sjoerg if (OldDepth < NumRetainedOuterLevels) 132*13fbcb42Sjoerg return OldDepth; 133*13fbcb42Sjoerg if (OldDepth < getNumLevels()) 134*13fbcb42Sjoerg return NumRetainedOuterLevels; 135*13fbcb42Sjoerg return OldDepth - TemplateArgumentLists.size(); 136*13fbcb42Sjoerg } 137*13fbcb42Sjoerg 13806f32e7eSjoerg /// Retrieve the template argument at a given depth and index. operator()13906f32e7eSjoerg const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { 14006f32e7eSjoerg assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 14106f32e7eSjoerg assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); 14206f32e7eSjoerg return TemplateArgumentLists[getNumLevels() - Depth - 1][Index]; 14306f32e7eSjoerg } 14406f32e7eSjoerg 14506f32e7eSjoerg /// Determine whether there is a non-NULL template argument at the 14606f32e7eSjoerg /// given depth and index. 14706f32e7eSjoerg /// 14806f32e7eSjoerg /// There must exist a template argument list at the given depth. hasTemplateArgument(unsigned Depth,unsigned Index)14906f32e7eSjoerg bool hasTemplateArgument(unsigned Depth, unsigned Index) const { 15006f32e7eSjoerg assert(Depth < getNumLevels()); 15106f32e7eSjoerg 15206f32e7eSjoerg if (Depth < NumRetainedOuterLevels) 15306f32e7eSjoerg return false; 15406f32e7eSjoerg 15506f32e7eSjoerg if (Index >= TemplateArgumentLists[getNumLevels() - Depth - 1].size()) 15606f32e7eSjoerg return false; 15706f32e7eSjoerg 15806f32e7eSjoerg return !(*this)(Depth, Index).isNull(); 15906f32e7eSjoerg } 16006f32e7eSjoerg 16106f32e7eSjoerg /// Clear out a specific template argument. setArgument(unsigned Depth,unsigned Index,TemplateArgument Arg)16206f32e7eSjoerg void setArgument(unsigned Depth, unsigned Index, 16306f32e7eSjoerg TemplateArgument Arg) { 16406f32e7eSjoerg assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 16506f32e7eSjoerg assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); 16606f32e7eSjoerg const_cast<TemplateArgument&>( 16706f32e7eSjoerg TemplateArgumentLists[getNumLevels() - Depth - 1][Index]) 16806f32e7eSjoerg = Arg; 16906f32e7eSjoerg } 17006f32e7eSjoerg 17106f32e7eSjoerg /// Add a new outermost level to the multi-level template argument 17206f32e7eSjoerg /// list. addOuterTemplateArguments(const TemplateArgumentList * TemplateArgs)17306f32e7eSjoerg void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { 17406f32e7eSjoerg addOuterTemplateArguments(ArgList(TemplateArgs->data(), 17506f32e7eSjoerg TemplateArgs->size())); 17606f32e7eSjoerg } 17706f32e7eSjoerg 17806f32e7eSjoerg /// Add a new outmost level to the multi-level template argument 17906f32e7eSjoerg /// list. addOuterTemplateArguments(ArgList Args)18006f32e7eSjoerg void addOuterTemplateArguments(ArgList Args) { 18106f32e7eSjoerg assert(!NumRetainedOuterLevels && 18206f32e7eSjoerg "substituted args outside retained args?"); 18306f32e7eSjoerg TemplateArgumentLists.push_back(Args); 18406f32e7eSjoerg } 18506f32e7eSjoerg 18606f32e7eSjoerg /// Add an outermost level that we are not substituting. We have no 18706f32e7eSjoerg /// arguments at this level, and do not remove it from the depth of inner 18806f32e7eSjoerg /// template parameters that we instantiate. addOuterRetainedLevel()18906f32e7eSjoerg void addOuterRetainedLevel() { 19006f32e7eSjoerg ++NumRetainedOuterLevels; 19106f32e7eSjoerg } addOuterRetainedLevels(unsigned Num)192*13fbcb42Sjoerg void addOuterRetainedLevels(unsigned Num) { 193*13fbcb42Sjoerg NumRetainedOuterLevels += Num; 194*13fbcb42Sjoerg } 19506f32e7eSjoerg 19606f32e7eSjoerg /// Retrieve the innermost template argument list. getInnermost()19706f32e7eSjoerg const ArgList &getInnermost() const { 19806f32e7eSjoerg return TemplateArgumentLists.front(); 19906f32e7eSjoerg } 20006f32e7eSjoerg }; 20106f32e7eSjoerg 20206f32e7eSjoerg /// The context in which partial ordering of function templates occurs. 20306f32e7eSjoerg enum TPOC { 20406f32e7eSjoerg /// Partial ordering of function templates for a function call. 20506f32e7eSjoerg TPOC_Call, 20606f32e7eSjoerg 20706f32e7eSjoerg /// Partial ordering of function templates for a call to a 20806f32e7eSjoerg /// conversion function. 20906f32e7eSjoerg TPOC_Conversion, 21006f32e7eSjoerg 21106f32e7eSjoerg /// Partial ordering of function templates in other contexts, e.g., 21206f32e7eSjoerg /// taking the address of a function template or matching a function 21306f32e7eSjoerg /// template specialization to a function template. 21406f32e7eSjoerg TPOC_Other 21506f32e7eSjoerg }; 21606f32e7eSjoerg 21706f32e7eSjoerg // This is lame but unavoidable in a world without forward 21806f32e7eSjoerg // declarations of enums. The alternatives are to either pollute 21906f32e7eSjoerg // Sema.h (by including this file) or sacrifice type safety (by 22006f32e7eSjoerg // making Sema.h declare things as enums). 22106f32e7eSjoerg class TemplatePartialOrderingContext { 22206f32e7eSjoerg TPOC Value; 22306f32e7eSjoerg 22406f32e7eSjoerg public: TemplatePartialOrderingContext(TPOC Value)22506f32e7eSjoerg TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} 22606f32e7eSjoerg TPOC()22706f32e7eSjoerg operator TPOC() const { return Value; } 22806f32e7eSjoerg }; 22906f32e7eSjoerg 23006f32e7eSjoerg /// Captures a template argument whose value has been deduced 23106f32e7eSjoerg /// via c++ template argument deduction. 23206f32e7eSjoerg class DeducedTemplateArgument : public TemplateArgument { 23306f32e7eSjoerg /// For a non-type template argument, whether the value was 23406f32e7eSjoerg /// deduced from an array bound. 23506f32e7eSjoerg bool DeducedFromArrayBound = false; 23606f32e7eSjoerg 23706f32e7eSjoerg public: 23806f32e7eSjoerg DeducedTemplateArgument() = default; 23906f32e7eSjoerg 24006f32e7eSjoerg DeducedTemplateArgument(const TemplateArgument &Arg, 24106f32e7eSjoerg bool DeducedFromArrayBound = false) TemplateArgument(Arg)24206f32e7eSjoerg : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {} 24306f32e7eSjoerg 24406f32e7eSjoerg /// Construct an integral non-type template argument that 24506f32e7eSjoerg /// has been deduced, possibly from an array bound. DeducedTemplateArgument(ASTContext & Ctx,const llvm::APSInt & Value,QualType ValueType,bool DeducedFromArrayBound)24606f32e7eSjoerg DeducedTemplateArgument(ASTContext &Ctx, 24706f32e7eSjoerg const llvm::APSInt &Value, 24806f32e7eSjoerg QualType ValueType, 24906f32e7eSjoerg bool DeducedFromArrayBound) 25006f32e7eSjoerg : TemplateArgument(Ctx, Value, ValueType), 25106f32e7eSjoerg DeducedFromArrayBound(DeducedFromArrayBound) {} 25206f32e7eSjoerg 25306f32e7eSjoerg /// For a non-type template argument, determine whether the 25406f32e7eSjoerg /// template argument was deduced from an array bound. wasDeducedFromArrayBound()25506f32e7eSjoerg bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } 25606f32e7eSjoerg 25706f32e7eSjoerg /// Specify whether the given non-type template argument 25806f32e7eSjoerg /// was deduced from an array bound. setDeducedFromArrayBound(bool Deduced)25906f32e7eSjoerg void setDeducedFromArrayBound(bool Deduced) { 26006f32e7eSjoerg DeducedFromArrayBound = Deduced; 26106f32e7eSjoerg } 26206f32e7eSjoerg }; 26306f32e7eSjoerg 26406f32e7eSjoerg /// A stack-allocated class that identifies which local 26506f32e7eSjoerg /// variable declaration instantiations are present in this scope. 26606f32e7eSjoerg /// 26706f32e7eSjoerg /// A new instance of this class type will be created whenever we 26806f32e7eSjoerg /// instantiate a new function declaration, which will have its own 26906f32e7eSjoerg /// set of parameter declarations. 27006f32e7eSjoerg class LocalInstantiationScope { 27106f32e7eSjoerg public: 27206f32e7eSjoerg /// A set of declarations. 27306f32e7eSjoerg using DeclArgumentPack = SmallVector<VarDecl *, 4>; 27406f32e7eSjoerg 27506f32e7eSjoerg private: 27606f32e7eSjoerg /// Reference to the semantic analysis that is performing 27706f32e7eSjoerg /// this template instantiation. 27806f32e7eSjoerg Sema &SemaRef; 27906f32e7eSjoerg 28006f32e7eSjoerg using LocalDeclsMap = 28106f32e7eSjoerg llvm::SmallDenseMap<const Decl *, 28206f32e7eSjoerg llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>; 28306f32e7eSjoerg 28406f32e7eSjoerg /// A mapping from local declarations that occur 28506f32e7eSjoerg /// within a template to their instantiations. 28606f32e7eSjoerg /// 28706f32e7eSjoerg /// This mapping is used during instantiation to keep track of, 28806f32e7eSjoerg /// e.g., function parameter and variable declarations. For example, 28906f32e7eSjoerg /// given: 29006f32e7eSjoerg /// 29106f32e7eSjoerg /// \code 29206f32e7eSjoerg /// template<typename T> T add(T x, T y) { return x + y; } 29306f32e7eSjoerg /// \endcode 29406f32e7eSjoerg /// 29506f32e7eSjoerg /// when we instantiate add<int>, we will introduce a mapping from 29606f32e7eSjoerg /// the ParmVarDecl for 'x' that occurs in the template to the 29706f32e7eSjoerg /// instantiated ParmVarDecl for 'x'. 29806f32e7eSjoerg /// 29906f32e7eSjoerg /// For a parameter pack, the local instantiation scope may contain a 30006f32e7eSjoerg /// set of instantiated parameters. This is stored as a DeclArgumentPack 30106f32e7eSjoerg /// pointer. 30206f32e7eSjoerg LocalDeclsMap LocalDecls; 30306f32e7eSjoerg 30406f32e7eSjoerg /// The set of argument packs we've allocated. 30506f32e7eSjoerg SmallVector<DeclArgumentPack *, 1> ArgumentPacks; 30606f32e7eSjoerg 30706f32e7eSjoerg /// The outer scope, which contains local variable 30806f32e7eSjoerg /// definitions from some other instantiation (that may not be 30906f32e7eSjoerg /// relevant to this particular scope). 31006f32e7eSjoerg LocalInstantiationScope *Outer; 31106f32e7eSjoerg 31206f32e7eSjoerg /// Whether we have already exited this scope. 31306f32e7eSjoerg bool Exited = false; 31406f32e7eSjoerg 31506f32e7eSjoerg /// Whether to combine this scope with the outer scope, such that 31606f32e7eSjoerg /// lookup will search our outer scope. 31706f32e7eSjoerg bool CombineWithOuterScope; 31806f32e7eSjoerg 31906f32e7eSjoerg /// If non-NULL, the template parameter pack that has been 32006f32e7eSjoerg /// partially substituted per C++0x [temp.arg.explicit]p9. 32106f32e7eSjoerg NamedDecl *PartiallySubstitutedPack = nullptr; 32206f32e7eSjoerg 32306f32e7eSjoerg /// If \c PartiallySubstitutedPack is non-null, the set of 32406f32e7eSjoerg /// explicitly-specified template arguments in that pack. 32506f32e7eSjoerg const TemplateArgument *ArgsInPartiallySubstitutedPack; 32606f32e7eSjoerg 32706f32e7eSjoerg /// If \c PartiallySubstitutedPack, the number of 32806f32e7eSjoerg /// explicitly-specified template arguments in 32906f32e7eSjoerg /// ArgsInPartiallySubstitutedPack. 33006f32e7eSjoerg unsigned NumArgsInPartiallySubstitutedPack; 33106f32e7eSjoerg 33206f32e7eSjoerg public: 33306f32e7eSjoerg LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) SemaRef(SemaRef)33406f32e7eSjoerg : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), 33506f32e7eSjoerg CombineWithOuterScope(CombineWithOuterScope) { 33606f32e7eSjoerg SemaRef.CurrentInstantiationScope = this; 33706f32e7eSjoerg } 33806f32e7eSjoerg 33906f32e7eSjoerg LocalInstantiationScope(const LocalInstantiationScope &) = delete; 34006f32e7eSjoerg LocalInstantiationScope & 34106f32e7eSjoerg operator=(const LocalInstantiationScope &) = delete; 34206f32e7eSjoerg ~LocalInstantiationScope()34306f32e7eSjoerg ~LocalInstantiationScope() { 34406f32e7eSjoerg Exit(); 34506f32e7eSjoerg } 34606f32e7eSjoerg getSema()34706f32e7eSjoerg const Sema &getSema() const { return SemaRef; } 34806f32e7eSjoerg 34906f32e7eSjoerg /// Exit this local instantiation scope early. Exit()35006f32e7eSjoerg void Exit() { 35106f32e7eSjoerg if (Exited) 35206f32e7eSjoerg return; 35306f32e7eSjoerg 35406f32e7eSjoerg for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I) 35506f32e7eSjoerg delete ArgumentPacks[I]; 35606f32e7eSjoerg 35706f32e7eSjoerg SemaRef.CurrentInstantiationScope = Outer; 35806f32e7eSjoerg Exited = true; 35906f32e7eSjoerg } 36006f32e7eSjoerg 36106f32e7eSjoerg /// Clone this scope, and all outer scopes, down to the given 36206f32e7eSjoerg /// outermost scope. cloneScopes(LocalInstantiationScope * Outermost)36306f32e7eSjoerg LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { 36406f32e7eSjoerg if (this == Outermost) return this; 36506f32e7eSjoerg 36606f32e7eSjoerg // Save the current scope from SemaRef since the LocalInstantiationScope 36706f32e7eSjoerg // will overwrite it on construction 36806f32e7eSjoerg LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope; 36906f32e7eSjoerg 37006f32e7eSjoerg LocalInstantiationScope *newScope = 37106f32e7eSjoerg new LocalInstantiationScope(SemaRef, CombineWithOuterScope); 37206f32e7eSjoerg 37306f32e7eSjoerg newScope->Outer = nullptr; 37406f32e7eSjoerg if (Outer) 37506f32e7eSjoerg newScope->Outer = Outer->cloneScopes(Outermost); 37606f32e7eSjoerg 37706f32e7eSjoerg newScope->PartiallySubstitutedPack = PartiallySubstitutedPack; 37806f32e7eSjoerg newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack; 37906f32e7eSjoerg newScope->NumArgsInPartiallySubstitutedPack = 38006f32e7eSjoerg NumArgsInPartiallySubstitutedPack; 38106f32e7eSjoerg 38206f32e7eSjoerg for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end(); 38306f32e7eSjoerg I != E; ++I) { 38406f32e7eSjoerg const Decl *D = I->first; 38506f32e7eSjoerg llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = 38606f32e7eSjoerg newScope->LocalDecls[D]; 38706f32e7eSjoerg if (I->second.is<Decl *>()) { 38806f32e7eSjoerg Stored = I->second.get<Decl *>(); 38906f32e7eSjoerg } else { 39006f32e7eSjoerg DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); 39106f32e7eSjoerg DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); 39206f32e7eSjoerg Stored = NewPack; 39306f32e7eSjoerg newScope->ArgumentPacks.push_back(NewPack); 39406f32e7eSjoerg } 39506f32e7eSjoerg } 39606f32e7eSjoerg // Restore the saved scope to SemaRef 39706f32e7eSjoerg SemaRef.CurrentInstantiationScope = oldScope; 39806f32e7eSjoerg return newScope; 39906f32e7eSjoerg } 40006f32e7eSjoerg 40106f32e7eSjoerg /// deletes the given scope, and all otuer scopes, down to the 40206f32e7eSjoerg /// given outermost scope. deleteScopes(LocalInstantiationScope * Scope,LocalInstantiationScope * Outermost)40306f32e7eSjoerg static void deleteScopes(LocalInstantiationScope *Scope, 40406f32e7eSjoerg LocalInstantiationScope *Outermost) { 40506f32e7eSjoerg while (Scope && Scope != Outermost) { 40606f32e7eSjoerg LocalInstantiationScope *Out = Scope->Outer; 40706f32e7eSjoerg delete Scope; 40806f32e7eSjoerg Scope = Out; 40906f32e7eSjoerg } 41006f32e7eSjoerg } 41106f32e7eSjoerg 41206f32e7eSjoerg /// Find the instantiation of the declaration D within the current 41306f32e7eSjoerg /// instantiation scope. 41406f32e7eSjoerg /// 41506f32e7eSjoerg /// \param D The declaration whose instantiation we are searching for. 41606f32e7eSjoerg /// 41706f32e7eSjoerg /// \returns A pointer to the declaration or argument pack of declarations 41806f32e7eSjoerg /// to which the declaration \c D is instantiated, if found. Otherwise, 41906f32e7eSjoerg /// returns NULL. 42006f32e7eSjoerg llvm::PointerUnion<Decl *, DeclArgumentPack *> * 42106f32e7eSjoerg findInstantiationOf(const Decl *D); 42206f32e7eSjoerg 42306f32e7eSjoerg void InstantiatedLocal(const Decl *D, Decl *Inst); 42406f32e7eSjoerg void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); 42506f32e7eSjoerg void MakeInstantiatedLocalArgPack(const Decl *D); 42606f32e7eSjoerg 42706f32e7eSjoerg /// Note that the given parameter pack has been partially substituted 42806f32e7eSjoerg /// via explicit specification of template arguments 42906f32e7eSjoerg /// (C++0x [temp.arg.explicit]p9). 43006f32e7eSjoerg /// 43106f32e7eSjoerg /// \param Pack The parameter pack, which will always be a template 43206f32e7eSjoerg /// parameter pack. 43306f32e7eSjoerg /// 43406f32e7eSjoerg /// \param ExplicitArgs The explicitly-specified template arguments provided 43506f32e7eSjoerg /// for this parameter pack. 43606f32e7eSjoerg /// 43706f32e7eSjoerg /// \param NumExplicitArgs The number of explicitly-specified template 43806f32e7eSjoerg /// arguments provided for this parameter pack. 43906f32e7eSjoerg void SetPartiallySubstitutedPack(NamedDecl *Pack, 44006f32e7eSjoerg const TemplateArgument *ExplicitArgs, 44106f32e7eSjoerg unsigned NumExplicitArgs); 44206f32e7eSjoerg 44306f32e7eSjoerg /// Reset the partially-substituted pack when it is no longer of 44406f32e7eSjoerg /// interest. ResetPartiallySubstitutedPack()44506f32e7eSjoerg void ResetPartiallySubstitutedPack() { 44606f32e7eSjoerg assert(PartiallySubstitutedPack && "No partially-substituted pack"); 44706f32e7eSjoerg PartiallySubstitutedPack = nullptr; 44806f32e7eSjoerg ArgsInPartiallySubstitutedPack = nullptr; 44906f32e7eSjoerg NumArgsInPartiallySubstitutedPack = 0; 45006f32e7eSjoerg } 45106f32e7eSjoerg 45206f32e7eSjoerg /// Retrieve the partially-substitued template parameter pack. 45306f32e7eSjoerg /// 45406f32e7eSjoerg /// If there is no partially-substituted parameter pack, returns NULL. 45506f32e7eSjoerg NamedDecl * 45606f32e7eSjoerg getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, 45706f32e7eSjoerg unsigned *NumExplicitArgs = nullptr) const; 458*13fbcb42Sjoerg 459*13fbcb42Sjoerg /// Determine whether D is a pack expansion created in this scope. 460*13fbcb42Sjoerg bool isLocalPackExpansion(const Decl *D); 46106f32e7eSjoerg }; 46206f32e7eSjoerg 46306f32e7eSjoerg class TemplateDeclInstantiator 46406f32e7eSjoerg : public DeclVisitor<TemplateDeclInstantiator, Decl *> 46506f32e7eSjoerg { 46606f32e7eSjoerg Sema &SemaRef; 46706f32e7eSjoerg Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; 46806f32e7eSjoerg DeclContext *Owner; 46906f32e7eSjoerg const MultiLevelTemplateArgumentList &TemplateArgs; 47006f32e7eSjoerg Sema::LateInstantiatedAttrVec* LateAttrs = nullptr; 47106f32e7eSjoerg LocalInstantiationScope *StartingScope = nullptr; 47206f32e7eSjoerg 47306f32e7eSjoerg /// A list of out-of-line class template partial 47406f32e7eSjoerg /// specializations that will need to be instantiated after the 47506f32e7eSjoerg /// enclosing class's instantiation is complete. 47606f32e7eSjoerg SmallVector<std::pair<ClassTemplateDecl *, 47706f32e7eSjoerg ClassTemplatePartialSpecializationDecl *>, 4> 47806f32e7eSjoerg OutOfLinePartialSpecs; 47906f32e7eSjoerg 48006f32e7eSjoerg /// A list of out-of-line variable template partial 48106f32e7eSjoerg /// specializations that will need to be instantiated after the 48206f32e7eSjoerg /// enclosing variable's instantiation is complete. 48306f32e7eSjoerg /// FIXME: Verify that this is needed. 48406f32e7eSjoerg SmallVector< 48506f32e7eSjoerg std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4> 48606f32e7eSjoerg OutOfLineVarPartialSpecs; 48706f32e7eSjoerg 48806f32e7eSjoerg public: TemplateDeclInstantiator(Sema & SemaRef,DeclContext * Owner,const MultiLevelTemplateArgumentList & TemplateArgs)48906f32e7eSjoerg TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, 49006f32e7eSjoerg const MultiLevelTemplateArgumentList &TemplateArgs) 49106f32e7eSjoerg : SemaRef(SemaRef), 49206f32e7eSjoerg SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), 49306f32e7eSjoerg Owner(Owner), TemplateArgs(TemplateArgs) {} 49406f32e7eSjoerg 49506f32e7eSjoerg // Define all the decl visitors using DeclNodes.inc 49606f32e7eSjoerg #define DECL(DERIVED, BASE) \ 49706f32e7eSjoerg Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D); 49806f32e7eSjoerg #define ABSTRACT_DECL(DECL) 49906f32e7eSjoerg 50006f32e7eSjoerg // Decls which never appear inside a class or function. 50106f32e7eSjoerg #define OBJCCONTAINER(DERIVED, BASE) 50206f32e7eSjoerg #define FILESCOPEASM(DERIVED, BASE) 50306f32e7eSjoerg #define IMPORT(DERIVED, BASE) 50406f32e7eSjoerg #define EXPORT(DERIVED, BASE) 50506f32e7eSjoerg #define LINKAGESPEC(DERIVED, BASE) 50606f32e7eSjoerg #define OBJCCOMPATIBLEALIAS(DERIVED, BASE) 50706f32e7eSjoerg #define OBJCMETHOD(DERIVED, BASE) 50806f32e7eSjoerg #define OBJCTYPEPARAM(DERIVED, BASE) 50906f32e7eSjoerg #define OBJCIVAR(DERIVED, BASE) 51006f32e7eSjoerg #define OBJCPROPERTY(DERIVED, BASE) 51106f32e7eSjoerg #define OBJCPROPERTYIMPL(DERIVED, BASE) 51206f32e7eSjoerg #define EMPTY(DERIVED, BASE) 513*13fbcb42Sjoerg #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE) 51406f32e7eSjoerg 51506f32e7eSjoerg // Decls which use special-case instantiation code. 51606f32e7eSjoerg #define BLOCK(DERIVED, BASE) 51706f32e7eSjoerg #define CAPTURED(DERIVED, BASE) 51806f32e7eSjoerg #define IMPLICITPARAM(DERIVED, BASE) 51906f32e7eSjoerg 52006f32e7eSjoerg #include "clang/AST/DeclNodes.inc" 52106f32e7eSjoerg 522*13fbcb42Sjoerg enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual }; 523*13fbcb42Sjoerg 524*13fbcb42Sjoerg void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T, 525*13fbcb42Sjoerg TypeSourceInfo *&TInfo, 526*13fbcb42Sjoerg DeclarationNameInfo &NameInfo); 527*13fbcb42Sjoerg 52806f32e7eSjoerg // A few supplemental visitor functions. 52906f32e7eSjoerg Decl *VisitCXXMethodDecl(CXXMethodDecl *D, 53006f32e7eSjoerg TemplateParameterList *TemplateParams, 53106f32e7eSjoerg Optional<const ASTTemplateArgumentListInfo *> 532*13fbcb42Sjoerg ClassScopeSpecializationArgs = llvm::None, 533*13fbcb42Sjoerg RewriteKind RK = RewriteKind::None); 53406f32e7eSjoerg Decl *VisitFunctionDecl(FunctionDecl *D, 535*13fbcb42Sjoerg TemplateParameterList *TemplateParams, 536*13fbcb42Sjoerg RewriteKind RK = RewriteKind::None); 53706f32e7eSjoerg Decl *VisitDecl(Decl *D); 53806f32e7eSjoerg Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, 53906f32e7eSjoerg ArrayRef<BindingDecl *> *Bindings = nullptr); 54006f32e7eSjoerg 54106f32e7eSjoerg // Enable late instantiation of attributes. Late instantiated attributes 54206f32e7eSjoerg // will be stored in LA. enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec * LA)54306f32e7eSjoerg void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) { 54406f32e7eSjoerg LateAttrs = LA; 54506f32e7eSjoerg StartingScope = SemaRef.CurrentInstantiationScope; 54606f32e7eSjoerg } 54706f32e7eSjoerg 54806f32e7eSjoerg // Disable late instantiation of attributes. disableLateAttributeInstantiation()54906f32e7eSjoerg void disableLateAttributeInstantiation() { 55006f32e7eSjoerg LateAttrs = nullptr; 55106f32e7eSjoerg StartingScope = nullptr; 55206f32e7eSjoerg } 55306f32e7eSjoerg getStartingScope()55406f32e7eSjoerg LocalInstantiationScope *getStartingScope() const { return StartingScope; } 55506f32e7eSjoerg 55606f32e7eSjoerg using delayed_partial_spec_iterator = SmallVectorImpl<std::pair< 55706f32e7eSjoerg ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator; 55806f32e7eSjoerg 55906f32e7eSjoerg using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair< 56006f32e7eSjoerg VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator; 56106f32e7eSjoerg 56206f32e7eSjoerg /// Return an iterator to the beginning of the set of 56306f32e7eSjoerg /// "delayed" partial specializations, which must be passed to 56406f32e7eSjoerg /// InstantiateClassTemplatePartialSpecialization once the class 56506f32e7eSjoerg /// definition has been completed. delayed_partial_spec_begin()56606f32e7eSjoerg delayed_partial_spec_iterator delayed_partial_spec_begin() { 56706f32e7eSjoerg return OutOfLinePartialSpecs.begin(); 56806f32e7eSjoerg } 56906f32e7eSjoerg delayed_var_partial_spec_begin()57006f32e7eSjoerg delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() { 57106f32e7eSjoerg return OutOfLineVarPartialSpecs.begin(); 57206f32e7eSjoerg } 57306f32e7eSjoerg 57406f32e7eSjoerg /// Return an iterator to the end of the set of 57506f32e7eSjoerg /// "delayed" partial specializations, which must be passed to 57606f32e7eSjoerg /// InstantiateClassTemplatePartialSpecialization once the class 57706f32e7eSjoerg /// definition has been completed. delayed_partial_spec_end()57806f32e7eSjoerg delayed_partial_spec_iterator delayed_partial_spec_end() { 57906f32e7eSjoerg return OutOfLinePartialSpecs.end(); 58006f32e7eSjoerg } 58106f32e7eSjoerg delayed_var_partial_spec_end()58206f32e7eSjoerg delayed_var_partial_spec_iterator delayed_var_partial_spec_end() { 58306f32e7eSjoerg return OutOfLineVarPartialSpecs.end(); 58406f32e7eSjoerg } 58506f32e7eSjoerg 58606f32e7eSjoerg // Helper functions for instantiating methods. 58706f32e7eSjoerg TypeSourceInfo *SubstFunctionType(FunctionDecl *D, 58806f32e7eSjoerg SmallVectorImpl<ParmVarDecl *> &Params); 58906f32e7eSjoerg bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); 59006f32e7eSjoerg bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); 59106f32e7eSjoerg 592*13fbcb42Sjoerg bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl); 593*13fbcb42Sjoerg 59406f32e7eSjoerg TemplateParameterList * 59506f32e7eSjoerg SubstTemplateParams(TemplateParameterList *List); 59606f32e7eSjoerg 59706f32e7eSjoerg bool SubstQualifier(const DeclaratorDecl *OldDecl, 59806f32e7eSjoerg DeclaratorDecl *NewDecl); 59906f32e7eSjoerg bool SubstQualifier(const TagDecl *OldDecl, 60006f32e7eSjoerg TagDecl *NewDecl); 60106f32e7eSjoerg 60206f32e7eSjoerg Decl *VisitVarTemplateSpecializationDecl( 603*13fbcb42Sjoerg VarTemplateDecl *VarTemplate, VarDecl *FromVar, 60406f32e7eSjoerg const TemplateArgumentListInfo &TemplateArgsInfo, 60506f32e7eSjoerg ArrayRef<TemplateArgument> Converted, 60606f32e7eSjoerg VarTemplateSpecializationDecl *PrevDecl = nullptr); 60706f32e7eSjoerg 60806f32e7eSjoerg Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); 60906f32e7eSjoerg ClassTemplatePartialSpecializationDecl * 61006f32e7eSjoerg InstantiateClassTemplatePartialSpecialization( 61106f32e7eSjoerg ClassTemplateDecl *ClassTemplate, 61206f32e7eSjoerg ClassTemplatePartialSpecializationDecl *PartialSpec); 61306f32e7eSjoerg VarTemplatePartialSpecializationDecl * 61406f32e7eSjoerg InstantiateVarTemplatePartialSpecialization( 61506f32e7eSjoerg VarTemplateDecl *VarTemplate, 61606f32e7eSjoerg VarTemplatePartialSpecializationDecl *PartialSpec); 61706f32e7eSjoerg void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern); 61806f32e7eSjoerg 61906f32e7eSjoerg private: 62006f32e7eSjoerg template<typename T> 62106f32e7eSjoerg Decl *instantiateUnresolvedUsingDecl(T *D, 62206f32e7eSjoerg bool InstantiatingPackElement = false); 62306f32e7eSjoerg }; 62406f32e7eSjoerg 62506f32e7eSjoerg } // namespace clang 62606f32e7eSjoerg 62706f32e7eSjoerg #endif // LLVM_CLANG_SEMA_TEMPLATE_H 628