1e5dd7070Spatrick //===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===// 2e5dd7070Spatrick // 3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information. 5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e5dd7070Spatrick //===----------------------------------------------------------------------===// 7e5dd7070Spatrick // 8e5dd7070Spatrick // This file provides types used in the semantic analysis of C++ templates. 9e5dd7070Spatrick // 10e5dd7070Spatrick //===----------------------------------------------------------------------===// 11e5dd7070Spatrick 12e5dd7070Spatrick #ifndef LLVM_CLANG_SEMA_TEMPLATE_H 13e5dd7070Spatrick #define LLVM_CLANG_SEMA_TEMPLATE_H 14e5dd7070Spatrick 15e5dd7070Spatrick #include "clang/AST/DeclTemplate.h" 16e5dd7070Spatrick #include "clang/AST/DeclVisitor.h" 17e5dd7070Spatrick #include "clang/AST/TemplateBase.h" 18e5dd7070Spatrick #include "clang/AST/Type.h" 19e5dd7070Spatrick #include "clang/Basic/LLVM.h" 20e5dd7070Spatrick #include "clang/Sema/Sema.h" 21e5dd7070Spatrick #include "llvm/ADT/ArrayRef.h" 22e5dd7070Spatrick #include "llvm/ADT/DenseMap.h" 23e5dd7070Spatrick #include "llvm/ADT/PointerUnion.h" 24e5dd7070Spatrick #include "llvm/ADT/SmallVector.h" 25e5dd7070Spatrick #include <cassert> 26*12c85518Srobert #include <optional> 27e5dd7070Spatrick #include <utility> 28e5dd7070Spatrick 29e5dd7070Spatrick namespace clang { 30e5dd7070Spatrick 31e5dd7070Spatrick class ASTContext; 32e5dd7070Spatrick class BindingDecl; 33e5dd7070Spatrick class CXXMethodDecl; 34e5dd7070Spatrick class Decl; 35e5dd7070Spatrick class DeclaratorDecl; 36e5dd7070Spatrick class DeclContext; 37e5dd7070Spatrick class EnumDecl; 38e5dd7070Spatrick class FunctionDecl; 39e5dd7070Spatrick class NamedDecl; 40e5dd7070Spatrick class ParmVarDecl; 41e5dd7070Spatrick class TagDecl; 42e5dd7070Spatrick class TypedefNameDecl; 43e5dd7070Spatrick class TypeSourceInfo; 44e5dd7070Spatrick class VarDecl; 45e5dd7070Spatrick 46ec727ea7Spatrick /// The kind of template substitution being performed. 47ec727ea7Spatrick enum class TemplateSubstitutionKind : char { 48ec727ea7Spatrick /// We are substituting template parameters for template arguments in order 49ec727ea7Spatrick /// to form a template specialization. 50ec727ea7Spatrick Specialization, 51ec727ea7Spatrick /// We are substituting template parameters for (typically) other template 52ec727ea7Spatrick /// parameters in order to rewrite a declaration as a different declaration 53ec727ea7Spatrick /// (for example, when forming a deduction guide from a constructor). 54ec727ea7Spatrick Rewrite, 55ec727ea7Spatrick }; 56ec727ea7Spatrick 57e5dd7070Spatrick /// Data structure that captures multiple levels of template argument 58e5dd7070Spatrick /// lists for use in template instantiation. 59e5dd7070Spatrick /// 60e5dd7070Spatrick /// Multiple levels of template arguments occur when instantiating the 61e5dd7070Spatrick /// definitions of member templates. For example: 62e5dd7070Spatrick /// 63e5dd7070Spatrick /// \code 64e5dd7070Spatrick /// template<typename T> 65e5dd7070Spatrick /// struct X { 66e5dd7070Spatrick /// template<T Value> 67e5dd7070Spatrick /// struct Y { 68e5dd7070Spatrick /// void f(); 69e5dd7070Spatrick /// }; 70e5dd7070Spatrick /// }; 71e5dd7070Spatrick /// \endcode 72e5dd7070Spatrick /// 73e5dd7070Spatrick /// When instantiating X<int>::Y<17>::f, the multi-level template argument 74e5dd7070Spatrick /// list will contain a template argument list (int) at depth 0 and a 75e5dd7070Spatrick /// template argument list (17) at depth 1. 76e5dd7070Spatrick class MultiLevelTemplateArgumentList { 77e5dd7070Spatrick /// The template argument list at a certain template depth 78*12c85518Srobert 79e5dd7070Spatrick using ArgList = ArrayRef<TemplateArgument>; 80*12c85518Srobert struct ArgumentListLevel { 81*12c85518Srobert llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal; 82*12c85518Srobert ArgList Args; 83*12c85518Srobert }; 84*12c85518Srobert using ContainerType = SmallVector<ArgumentListLevel, 4>; 85*12c85518Srobert 86*12c85518Srobert using ArgListsIterator = ContainerType::iterator; 87*12c85518Srobert using ConstArgListsIterator = ContainerType::const_iterator; 88e5dd7070Spatrick 89e5dd7070Spatrick /// The template argument lists, stored from the innermost template 90e5dd7070Spatrick /// argument list (first) to the outermost template argument list (last). 91*12c85518Srobert ContainerType TemplateArgumentLists; 92e5dd7070Spatrick 93e5dd7070Spatrick /// The number of outer levels of template arguments that are not 94e5dd7070Spatrick /// being substituted. 95e5dd7070Spatrick unsigned NumRetainedOuterLevels = 0; 96e5dd7070Spatrick 97ec727ea7Spatrick /// The kind of substitution described by this argument list. 98ec727ea7Spatrick TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization; 99ec727ea7Spatrick 100e5dd7070Spatrick public: 101e5dd7070Spatrick /// Construct an empty set of template argument lists. 102e5dd7070Spatrick MultiLevelTemplateArgumentList() = default; 103e5dd7070Spatrick 104e5dd7070Spatrick /// Construct a single-level template argument list. MultiLevelTemplateArgumentList(Decl * D,ArgList Args,bool Final)105*12c85518Srobert MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) { 106*12c85518Srobert addOuterTemplateArguments(D, Args, Final); 107e5dd7070Spatrick } 108e5dd7070Spatrick setKind(TemplateSubstitutionKind K)109ec727ea7Spatrick void setKind(TemplateSubstitutionKind K) { Kind = K; } 110ec727ea7Spatrick 111ec727ea7Spatrick /// Determine the kind of template substitution being performed. getKind()112ec727ea7Spatrick TemplateSubstitutionKind getKind() const { return Kind; } 113ec727ea7Spatrick 114ec727ea7Spatrick /// Determine whether we are rewriting template parameters rather than 115ec727ea7Spatrick /// substituting for them. If so, we should not leave references to the 116ec727ea7Spatrick /// original template parameters behind. isRewrite()117ec727ea7Spatrick bool isRewrite() const { 118ec727ea7Spatrick return Kind == TemplateSubstitutionKind::Rewrite; 119ec727ea7Spatrick } 120ec727ea7Spatrick 121e5dd7070Spatrick /// Determine the number of levels in this template argument 122e5dd7070Spatrick /// list. getNumLevels()123e5dd7070Spatrick unsigned getNumLevels() const { 124e5dd7070Spatrick return TemplateArgumentLists.size() + NumRetainedOuterLevels; 125e5dd7070Spatrick } 126e5dd7070Spatrick 127e5dd7070Spatrick /// Determine the number of substituted levels in this template 128e5dd7070Spatrick /// argument list. getNumSubstitutedLevels()129e5dd7070Spatrick unsigned getNumSubstitutedLevels() const { 130e5dd7070Spatrick return TemplateArgumentLists.size(); 131e5dd7070Spatrick } 132e5dd7070Spatrick 133*12c85518Srobert // Determine the number of substituted args at 'Depth'. getNumSubsitutedArgs(unsigned Depth)134*12c85518Srobert unsigned getNumSubsitutedArgs(unsigned Depth) const { 135*12c85518Srobert assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 136*12c85518Srobert return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size(); 137*12c85518Srobert } 138*12c85518Srobert getNumRetainedOuterLevels()139ec727ea7Spatrick unsigned getNumRetainedOuterLevels() const { 140ec727ea7Spatrick return NumRetainedOuterLevels; 141ec727ea7Spatrick } 142ec727ea7Spatrick 143e5dd7070Spatrick /// Determine how many of the \p OldDepth outermost template parameter 144e5dd7070Spatrick /// lists would be removed by substituting these arguments. getNewDepth(unsigned OldDepth)145e5dd7070Spatrick unsigned getNewDepth(unsigned OldDepth) const { 146e5dd7070Spatrick if (OldDepth < NumRetainedOuterLevels) 147e5dd7070Spatrick return OldDepth; 148e5dd7070Spatrick if (OldDepth < getNumLevels()) 149e5dd7070Spatrick return NumRetainedOuterLevels; 150e5dd7070Spatrick return OldDepth - TemplateArgumentLists.size(); 151e5dd7070Spatrick } 152e5dd7070Spatrick 153e5dd7070Spatrick /// Retrieve the template argument at a given depth and index. operator()154e5dd7070Spatrick const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { 155e5dd7070Spatrick assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 156*12c85518Srobert assert(Index < 157*12c85518Srobert TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); 158*12c85518Srobert return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]; 159*12c85518Srobert } 160*12c85518Srobert 161*12c85518Srobert /// A template-like entity which owns the whole pattern being substituted. 162*12c85518Srobert /// This will usually own a set of template parameters, or in some 163*12c85518Srobert /// cases might even be a template parameter itself. getAssociatedDecl(unsigned Depth)164*12c85518Srobert std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const { 165*12c85518Srobert assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 166*12c85518Srobert auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1] 167*12c85518Srobert .AssociatedDeclAndFinal; 168*12c85518Srobert return {AD.getPointer(), AD.getInt()}; 169e5dd7070Spatrick } 170e5dd7070Spatrick 171e5dd7070Spatrick /// Determine whether there is a non-NULL template argument at the 172e5dd7070Spatrick /// given depth and index. 173e5dd7070Spatrick /// 174e5dd7070Spatrick /// There must exist a template argument list at the given depth. hasTemplateArgument(unsigned Depth,unsigned Index)175e5dd7070Spatrick bool hasTemplateArgument(unsigned Depth, unsigned Index) const { 176e5dd7070Spatrick assert(Depth < getNumLevels()); 177e5dd7070Spatrick 178e5dd7070Spatrick if (Depth < NumRetainedOuterLevels) 179e5dd7070Spatrick return false; 180e5dd7070Spatrick 181*12c85518Srobert if (Index >= 182*12c85518Srobert TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()) 183e5dd7070Spatrick return false; 184e5dd7070Spatrick 185e5dd7070Spatrick return !(*this)(Depth, Index).isNull(); 186e5dd7070Spatrick } 187e5dd7070Spatrick isAnyArgInstantiationDependent()188*12c85518Srobert bool isAnyArgInstantiationDependent() const { 189*12c85518Srobert for (ArgumentListLevel ListLevel : TemplateArgumentLists) 190*12c85518Srobert for (const TemplateArgument &TA : ListLevel.Args) 191*12c85518Srobert if (TA.isInstantiationDependent()) 192*12c85518Srobert return true; 193*12c85518Srobert return false; 194*12c85518Srobert } 195*12c85518Srobert 196e5dd7070Spatrick /// Clear out a specific template argument. setArgument(unsigned Depth,unsigned Index,TemplateArgument Arg)197e5dd7070Spatrick void setArgument(unsigned Depth, unsigned Index, 198e5dd7070Spatrick TemplateArgument Arg) { 199e5dd7070Spatrick assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); 200*12c85518Srobert assert(Index < 201*12c85518Srobert TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size()); 202e5dd7070Spatrick const_cast<TemplateArgument &>( 203*12c85518Srobert TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg; 204e5dd7070Spatrick } 205e5dd7070Spatrick 206e5dd7070Spatrick /// Add a new outmost level to the multi-level template argument 207e5dd7070Spatrick /// list. 208*12c85518Srobert /// A 'Final' substitution means that Subst* nodes won't be built 209*12c85518Srobert /// for the replacements. addOuterTemplateArguments(Decl * AssociatedDecl,ArgList Args,bool Final)210*12c85518Srobert void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, 211*12c85518Srobert bool Final) { 212*12c85518Srobert assert(!NumRetainedOuterLevels && 213*12c85518Srobert "substituted args outside retained args?"); 214*12c85518Srobert assert(getKind() == TemplateSubstitutionKind::Specialization); 215*12c85518Srobert TemplateArgumentLists.push_back( 216*12c85518Srobert {{AssociatedDecl->getCanonicalDecl(), Final}, Args}); 217*12c85518Srobert } 218*12c85518Srobert addOuterTemplateArguments(ArgList Args)219e5dd7070Spatrick void addOuterTemplateArguments(ArgList Args) { 220e5dd7070Spatrick assert(!NumRetainedOuterLevels && 221e5dd7070Spatrick "substituted args outside retained args?"); 222*12c85518Srobert assert(getKind() == TemplateSubstitutionKind::Rewrite); 223*12c85518Srobert TemplateArgumentLists.push_back({{}, Args}); 224*12c85518Srobert } 225*12c85518Srobert addOuterTemplateArguments(std::nullopt_t)226*12c85518Srobert void addOuterTemplateArguments(std::nullopt_t) { 227*12c85518Srobert assert(!NumRetainedOuterLevels && 228*12c85518Srobert "substituted args outside retained args?"); 229*12c85518Srobert TemplateArgumentLists.push_back({}); 230*12c85518Srobert } 231*12c85518Srobert 232*12c85518Srobert /// Replaces the current 'innermost' level with the provided argument list. 233*12c85518Srobert /// This is useful for type deduction cases where we need to get the entire 234*12c85518Srobert /// list from the AST, but then add the deduced innermost list. replaceInnermostTemplateArguments(ArgList Args)235*12c85518Srobert void replaceInnermostTemplateArguments(ArgList Args) { 236*12c85518Srobert assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); 237*12c85518Srobert TemplateArgumentLists[0].Args = Args; 238e5dd7070Spatrick } 239e5dd7070Spatrick 240e5dd7070Spatrick /// Add an outermost level that we are not substituting. We have no 241e5dd7070Spatrick /// arguments at this level, and do not remove it from the depth of inner 242e5dd7070Spatrick /// template parameters that we instantiate. addOuterRetainedLevel()243e5dd7070Spatrick void addOuterRetainedLevel() { 244e5dd7070Spatrick ++NumRetainedOuterLevels; 245e5dd7070Spatrick } addOuterRetainedLevels(unsigned Num)246ec727ea7Spatrick void addOuterRetainedLevels(unsigned Num) { 247ec727ea7Spatrick NumRetainedOuterLevels += Num; 248ec727ea7Spatrick } 249e5dd7070Spatrick 250e5dd7070Spatrick /// Retrieve the innermost template argument list. getInnermost()251e5dd7070Spatrick const ArgList &getInnermost() const { 252*12c85518Srobert return TemplateArgumentLists.front().Args; 253e5dd7070Spatrick } 254*12c85518Srobert /// Retrieve the outermost template argument list. getOutermost()255*12c85518Srobert const ArgList &getOutermost() const { 256*12c85518Srobert return TemplateArgumentLists.back().Args; 257*12c85518Srobert } begin()258*12c85518Srobert ArgListsIterator begin() { return TemplateArgumentLists.begin(); } begin()259*12c85518Srobert ConstArgListsIterator begin() const { 260*12c85518Srobert return TemplateArgumentLists.begin(); 261*12c85518Srobert } end()262*12c85518Srobert ArgListsIterator end() { return TemplateArgumentLists.end(); } end()263*12c85518Srobert ConstArgListsIterator end() const { return TemplateArgumentLists.end(); } 264e5dd7070Spatrick }; 265e5dd7070Spatrick 266e5dd7070Spatrick /// The context in which partial ordering of function templates occurs. 267e5dd7070Spatrick enum TPOC { 268e5dd7070Spatrick /// Partial ordering of function templates for a function call. 269e5dd7070Spatrick TPOC_Call, 270e5dd7070Spatrick 271e5dd7070Spatrick /// Partial ordering of function templates for a call to a 272e5dd7070Spatrick /// conversion function. 273e5dd7070Spatrick TPOC_Conversion, 274e5dd7070Spatrick 275e5dd7070Spatrick /// Partial ordering of function templates in other contexts, e.g., 276e5dd7070Spatrick /// taking the address of a function template or matching a function 277e5dd7070Spatrick /// template specialization to a function template. 278e5dd7070Spatrick TPOC_Other 279e5dd7070Spatrick }; 280e5dd7070Spatrick 281e5dd7070Spatrick // This is lame but unavoidable in a world without forward 282e5dd7070Spatrick // declarations of enums. The alternatives are to either pollute 283e5dd7070Spatrick // Sema.h (by including this file) or sacrifice type safety (by 284e5dd7070Spatrick // making Sema.h declare things as enums). 285e5dd7070Spatrick class TemplatePartialOrderingContext { 286e5dd7070Spatrick TPOC Value; 287e5dd7070Spatrick 288e5dd7070Spatrick public: TemplatePartialOrderingContext(TPOC Value)289e5dd7070Spatrick TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} 290e5dd7070Spatrick TPOC()291e5dd7070Spatrick operator TPOC() const { return Value; } 292e5dd7070Spatrick }; 293e5dd7070Spatrick 294e5dd7070Spatrick /// Captures a template argument whose value has been deduced 295e5dd7070Spatrick /// via c++ template argument deduction. 296e5dd7070Spatrick class DeducedTemplateArgument : public TemplateArgument { 297e5dd7070Spatrick /// For a non-type template argument, whether the value was 298e5dd7070Spatrick /// deduced from an array bound. 299e5dd7070Spatrick bool DeducedFromArrayBound = false; 300e5dd7070Spatrick 301e5dd7070Spatrick public: 302e5dd7070Spatrick DeducedTemplateArgument() = default; 303e5dd7070Spatrick 304e5dd7070Spatrick DeducedTemplateArgument(const TemplateArgument &Arg, 305e5dd7070Spatrick bool DeducedFromArrayBound = false) TemplateArgument(Arg)306e5dd7070Spatrick : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {} 307e5dd7070Spatrick 308e5dd7070Spatrick /// Construct an integral non-type template argument that 309e5dd7070Spatrick /// has been deduced, possibly from an array bound. DeducedTemplateArgument(ASTContext & Ctx,const llvm::APSInt & Value,QualType ValueType,bool DeducedFromArrayBound)310e5dd7070Spatrick DeducedTemplateArgument(ASTContext &Ctx, 311e5dd7070Spatrick const llvm::APSInt &Value, 312e5dd7070Spatrick QualType ValueType, 313e5dd7070Spatrick bool DeducedFromArrayBound) 314e5dd7070Spatrick : TemplateArgument(Ctx, Value, ValueType), 315e5dd7070Spatrick DeducedFromArrayBound(DeducedFromArrayBound) {} 316e5dd7070Spatrick 317e5dd7070Spatrick /// For a non-type template argument, determine whether the 318e5dd7070Spatrick /// template argument was deduced from an array bound. wasDeducedFromArrayBound()319e5dd7070Spatrick bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } 320e5dd7070Spatrick 321e5dd7070Spatrick /// Specify whether the given non-type template argument 322e5dd7070Spatrick /// was deduced from an array bound. setDeducedFromArrayBound(bool Deduced)323e5dd7070Spatrick void setDeducedFromArrayBound(bool Deduced) { 324e5dd7070Spatrick DeducedFromArrayBound = Deduced; 325e5dd7070Spatrick } 326e5dd7070Spatrick }; 327e5dd7070Spatrick 328e5dd7070Spatrick /// A stack-allocated class that identifies which local 329e5dd7070Spatrick /// variable declaration instantiations are present in this scope. 330e5dd7070Spatrick /// 331e5dd7070Spatrick /// A new instance of this class type will be created whenever we 332e5dd7070Spatrick /// instantiate a new function declaration, which will have its own 333e5dd7070Spatrick /// set of parameter declarations. 334e5dd7070Spatrick class LocalInstantiationScope { 335e5dd7070Spatrick public: 336e5dd7070Spatrick /// A set of declarations. 337e5dd7070Spatrick using DeclArgumentPack = SmallVector<VarDecl *, 4>; 338e5dd7070Spatrick 339e5dd7070Spatrick private: 340e5dd7070Spatrick /// Reference to the semantic analysis that is performing 341e5dd7070Spatrick /// this template instantiation. 342e5dd7070Spatrick Sema &SemaRef; 343e5dd7070Spatrick 344e5dd7070Spatrick using LocalDeclsMap = 345e5dd7070Spatrick llvm::SmallDenseMap<const Decl *, 346e5dd7070Spatrick llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>; 347e5dd7070Spatrick 348e5dd7070Spatrick /// A mapping from local declarations that occur 349e5dd7070Spatrick /// within a template to their instantiations. 350e5dd7070Spatrick /// 351e5dd7070Spatrick /// This mapping is used during instantiation to keep track of, 352e5dd7070Spatrick /// e.g., function parameter and variable declarations. For example, 353e5dd7070Spatrick /// given: 354e5dd7070Spatrick /// 355e5dd7070Spatrick /// \code 356e5dd7070Spatrick /// template<typename T> T add(T x, T y) { return x + y; } 357e5dd7070Spatrick /// \endcode 358e5dd7070Spatrick /// 359e5dd7070Spatrick /// when we instantiate add<int>, we will introduce a mapping from 360e5dd7070Spatrick /// the ParmVarDecl for 'x' that occurs in the template to the 361e5dd7070Spatrick /// instantiated ParmVarDecl for 'x'. 362e5dd7070Spatrick /// 363e5dd7070Spatrick /// For a parameter pack, the local instantiation scope may contain a 364e5dd7070Spatrick /// set of instantiated parameters. This is stored as a DeclArgumentPack 365e5dd7070Spatrick /// pointer. 366e5dd7070Spatrick LocalDeclsMap LocalDecls; 367e5dd7070Spatrick 368e5dd7070Spatrick /// The set of argument packs we've allocated. 369e5dd7070Spatrick SmallVector<DeclArgumentPack *, 1> ArgumentPacks; 370e5dd7070Spatrick 371e5dd7070Spatrick /// The outer scope, which contains local variable 372e5dd7070Spatrick /// definitions from some other instantiation (that may not be 373e5dd7070Spatrick /// relevant to this particular scope). 374e5dd7070Spatrick LocalInstantiationScope *Outer; 375e5dd7070Spatrick 376e5dd7070Spatrick /// Whether we have already exited this scope. 377e5dd7070Spatrick bool Exited = false; 378e5dd7070Spatrick 379e5dd7070Spatrick /// Whether to combine this scope with the outer scope, such that 380e5dd7070Spatrick /// lookup will search our outer scope. 381e5dd7070Spatrick bool CombineWithOuterScope; 382e5dd7070Spatrick 383e5dd7070Spatrick /// If non-NULL, the template parameter pack that has been 384e5dd7070Spatrick /// partially substituted per C++0x [temp.arg.explicit]p9. 385e5dd7070Spatrick NamedDecl *PartiallySubstitutedPack = nullptr; 386e5dd7070Spatrick 387e5dd7070Spatrick /// If \c PartiallySubstitutedPack is non-null, the set of 388e5dd7070Spatrick /// explicitly-specified template arguments in that pack. 389e5dd7070Spatrick const TemplateArgument *ArgsInPartiallySubstitutedPack; 390e5dd7070Spatrick 391e5dd7070Spatrick /// If \c PartiallySubstitutedPack, the number of 392e5dd7070Spatrick /// explicitly-specified template arguments in 393e5dd7070Spatrick /// ArgsInPartiallySubstitutedPack. 394e5dd7070Spatrick unsigned NumArgsInPartiallySubstitutedPack; 395e5dd7070Spatrick 396e5dd7070Spatrick public: 397e5dd7070Spatrick LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) SemaRef(SemaRef)398e5dd7070Spatrick : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), 399e5dd7070Spatrick CombineWithOuterScope(CombineWithOuterScope) { 400e5dd7070Spatrick SemaRef.CurrentInstantiationScope = this; 401e5dd7070Spatrick } 402e5dd7070Spatrick 403e5dd7070Spatrick LocalInstantiationScope(const LocalInstantiationScope &) = delete; 404e5dd7070Spatrick LocalInstantiationScope & 405e5dd7070Spatrick operator=(const LocalInstantiationScope &) = delete; 406e5dd7070Spatrick ~LocalInstantiationScope()407e5dd7070Spatrick ~LocalInstantiationScope() { 408e5dd7070Spatrick Exit(); 409e5dd7070Spatrick } 410e5dd7070Spatrick getSema()411e5dd7070Spatrick const Sema &getSema() const { return SemaRef; } 412e5dd7070Spatrick 413e5dd7070Spatrick /// Exit this local instantiation scope early. Exit()414e5dd7070Spatrick void Exit() { 415e5dd7070Spatrick if (Exited) 416e5dd7070Spatrick return; 417e5dd7070Spatrick 418e5dd7070Spatrick for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I) 419e5dd7070Spatrick delete ArgumentPacks[I]; 420e5dd7070Spatrick 421e5dd7070Spatrick SemaRef.CurrentInstantiationScope = Outer; 422e5dd7070Spatrick Exited = true; 423e5dd7070Spatrick } 424e5dd7070Spatrick 425e5dd7070Spatrick /// Clone this scope, and all outer scopes, down to the given 426e5dd7070Spatrick /// outermost scope. cloneScopes(LocalInstantiationScope * Outermost)427e5dd7070Spatrick LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { 428e5dd7070Spatrick if (this == Outermost) return this; 429e5dd7070Spatrick 430e5dd7070Spatrick // Save the current scope from SemaRef since the LocalInstantiationScope 431e5dd7070Spatrick // will overwrite it on construction 432e5dd7070Spatrick LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope; 433e5dd7070Spatrick 434e5dd7070Spatrick LocalInstantiationScope *newScope = 435e5dd7070Spatrick new LocalInstantiationScope(SemaRef, CombineWithOuterScope); 436e5dd7070Spatrick 437e5dd7070Spatrick newScope->Outer = nullptr; 438e5dd7070Spatrick if (Outer) 439e5dd7070Spatrick newScope->Outer = Outer->cloneScopes(Outermost); 440e5dd7070Spatrick 441e5dd7070Spatrick newScope->PartiallySubstitutedPack = PartiallySubstitutedPack; 442e5dd7070Spatrick newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack; 443e5dd7070Spatrick newScope->NumArgsInPartiallySubstitutedPack = 444e5dd7070Spatrick NumArgsInPartiallySubstitutedPack; 445e5dd7070Spatrick 446e5dd7070Spatrick for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end(); 447e5dd7070Spatrick I != E; ++I) { 448e5dd7070Spatrick const Decl *D = I->first; 449e5dd7070Spatrick llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = 450e5dd7070Spatrick newScope->LocalDecls[D]; 451e5dd7070Spatrick if (I->second.is<Decl *>()) { 452e5dd7070Spatrick Stored = I->second.get<Decl *>(); 453e5dd7070Spatrick } else { 454e5dd7070Spatrick DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); 455e5dd7070Spatrick DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); 456e5dd7070Spatrick Stored = NewPack; 457e5dd7070Spatrick newScope->ArgumentPacks.push_back(NewPack); 458e5dd7070Spatrick } 459e5dd7070Spatrick } 460e5dd7070Spatrick // Restore the saved scope to SemaRef 461e5dd7070Spatrick SemaRef.CurrentInstantiationScope = oldScope; 462e5dd7070Spatrick return newScope; 463e5dd7070Spatrick } 464e5dd7070Spatrick 465*12c85518Srobert /// deletes the given scope, and all outer scopes, down to the 466e5dd7070Spatrick /// given outermost scope. deleteScopes(LocalInstantiationScope * Scope,LocalInstantiationScope * Outermost)467e5dd7070Spatrick static void deleteScopes(LocalInstantiationScope *Scope, 468e5dd7070Spatrick LocalInstantiationScope *Outermost) { 469e5dd7070Spatrick while (Scope && Scope != Outermost) { 470e5dd7070Spatrick LocalInstantiationScope *Out = Scope->Outer; 471e5dd7070Spatrick delete Scope; 472e5dd7070Spatrick Scope = Out; 473e5dd7070Spatrick } 474e5dd7070Spatrick } 475e5dd7070Spatrick 476e5dd7070Spatrick /// Find the instantiation of the declaration D within the current 477e5dd7070Spatrick /// instantiation scope. 478e5dd7070Spatrick /// 479e5dd7070Spatrick /// \param D The declaration whose instantiation we are searching for. 480e5dd7070Spatrick /// 481e5dd7070Spatrick /// \returns A pointer to the declaration or argument pack of declarations 482e5dd7070Spatrick /// to which the declaration \c D is instantiated, if found. Otherwise, 483e5dd7070Spatrick /// returns NULL. 484e5dd7070Spatrick llvm::PointerUnion<Decl *, DeclArgumentPack *> * 485e5dd7070Spatrick findInstantiationOf(const Decl *D); 486e5dd7070Spatrick 487e5dd7070Spatrick void InstantiatedLocal(const Decl *D, Decl *Inst); 488e5dd7070Spatrick void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); 489e5dd7070Spatrick void MakeInstantiatedLocalArgPack(const Decl *D); 490e5dd7070Spatrick 491e5dd7070Spatrick /// Note that the given parameter pack has been partially substituted 492e5dd7070Spatrick /// via explicit specification of template arguments 493e5dd7070Spatrick /// (C++0x [temp.arg.explicit]p9). 494e5dd7070Spatrick /// 495e5dd7070Spatrick /// \param Pack The parameter pack, which will always be a template 496e5dd7070Spatrick /// parameter pack. 497e5dd7070Spatrick /// 498e5dd7070Spatrick /// \param ExplicitArgs The explicitly-specified template arguments provided 499e5dd7070Spatrick /// for this parameter pack. 500e5dd7070Spatrick /// 501e5dd7070Spatrick /// \param NumExplicitArgs The number of explicitly-specified template 502e5dd7070Spatrick /// arguments provided for this parameter pack. 503e5dd7070Spatrick void SetPartiallySubstitutedPack(NamedDecl *Pack, 504e5dd7070Spatrick const TemplateArgument *ExplicitArgs, 505e5dd7070Spatrick unsigned NumExplicitArgs); 506e5dd7070Spatrick 507e5dd7070Spatrick /// Reset the partially-substituted pack when it is no longer of 508e5dd7070Spatrick /// interest. ResetPartiallySubstitutedPack()509e5dd7070Spatrick void ResetPartiallySubstitutedPack() { 510e5dd7070Spatrick assert(PartiallySubstitutedPack && "No partially-substituted pack"); 511e5dd7070Spatrick PartiallySubstitutedPack = nullptr; 512e5dd7070Spatrick ArgsInPartiallySubstitutedPack = nullptr; 513e5dd7070Spatrick NumArgsInPartiallySubstitutedPack = 0; 514e5dd7070Spatrick } 515e5dd7070Spatrick 516e5dd7070Spatrick /// Retrieve the partially-substitued template parameter pack. 517e5dd7070Spatrick /// 518e5dd7070Spatrick /// If there is no partially-substituted parameter pack, returns NULL. 519e5dd7070Spatrick NamedDecl * 520e5dd7070Spatrick getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, 521e5dd7070Spatrick unsigned *NumExplicitArgs = nullptr) const; 522ec727ea7Spatrick 523ec727ea7Spatrick /// Determine whether D is a pack expansion created in this scope. 524ec727ea7Spatrick bool isLocalPackExpansion(const Decl *D); 525e5dd7070Spatrick }; 526e5dd7070Spatrick 527e5dd7070Spatrick class TemplateDeclInstantiator 528e5dd7070Spatrick : public DeclVisitor<TemplateDeclInstantiator, Decl *> 529e5dd7070Spatrick { 530e5dd7070Spatrick Sema &SemaRef; 531e5dd7070Spatrick Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; 532e5dd7070Spatrick DeclContext *Owner; 533e5dd7070Spatrick const MultiLevelTemplateArgumentList &TemplateArgs; 534e5dd7070Spatrick Sema::LateInstantiatedAttrVec* LateAttrs = nullptr; 535e5dd7070Spatrick LocalInstantiationScope *StartingScope = nullptr; 536*12c85518Srobert bool EvaluateConstraints = true; 537e5dd7070Spatrick 538e5dd7070Spatrick /// A list of out-of-line class template partial 539e5dd7070Spatrick /// specializations that will need to be instantiated after the 540e5dd7070Spatrick /// enclosing class's instantiation is complete. 541e5dd7070Spatrick SmallVector<std::pair<ClassTemplateDecl *, 542e5dd7070Spatrick ClassTemplatePartialSpecializationDecl *>, 4> 543e5dd7070Spatrick OutOfLinePartialSpecs; 544e5dd7070Spatrick 545e5dd7070Spatrick /// A list of out-of-line variable template partial 546e5dd7070Spatrick /// specializations that will need to be instantiated after the 547e5dd7070Spatrick /// enclosing variable's instantiation is complete. 548e5dd7070Spatrick /// FIXME: Verify that this is needed. 549e5dd7070Spatrick SmallVector< 550e5dd7070Spatrick std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4> 551e5dd7070Spatrick OutOfLineVarPartialSpecs; 552e5dd7070Spatrick 553e5dd7070Spatrick public: TemplateDeclInstantiator(Sema & SemaRef,DeclContext * Owner,const MultiLevelTemplateArgumentList & TemplateArgs)554e5dd7070Spatrick TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, 555e5dd7070Spatrick const MultiLevelTemplateArgumentList &TemplateArgs) 556e5dd7070Spatrick : SemaRef(SemaRef), 557e5dd7070Spatrick SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), 558e5dd7070Spatrick Owner(Owner), TemplateArgs(TemplateArgs) {} 559e5dd7070Spatrick setEvaluateConstraints(bool B)560*12c85518Srobert void setEvaluateConstraints(bool B) { 561*12c85518Srobert EvaluateConstraints = B; 562*12c85518Srobert } getEvaluateConstraints()563*12c85518Srobert bool getEvaluateConstraints() { 564*12c85518Srobert return EvaluateConstraints; 565*12c85518Srobert } 566*12c85518Srobert 567e5dd7070Spatrick // Define all the decl visitors using DeclNodes.inc 568e5dd7070Spatrick #define DECL(DERIVED, BASE) \ 569e5dd7070Spatrick Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D); 570e5dd7070Spatrick #define ABSTRACT_DECL(DECL) 571e5dd7070Spatrick 572e5dd7070Spatrick // Decls which never appear inside a class or function. 573e5dd7070Spatrick #define OBJCCONTAINER(DERIVED, BASE) 574e5dd7070Spatrick #define FILESCOPEASM(DERIVED, BASE) 575*12c85518Srobert #define TOPLEVELSTMT(DERIVED, BASE) 576e5dd7070Spatrick #define IMPORT(DERIVED, BASE) 577e5dd7070Spatrick #define EXPORT(DERIVED, BASE) 578e5dd7070Spatrick #define LINKAGESPEC(DERIVED, BASE) 579e5dd7070Spatrick #define OBJCCOMPATIBLEALIAS(DERIVED, BASE) 580e5dd7070Spatrick #define OBJCMETHOD(DERIVED, BASE) 581e5dd7070Spatrick #define OBJCTYPEPARAM(DERIVED, BASE) 582e5dd7070Spatrick #define OBJCIVAR(DERIVED, BASE) 583e5dd7070Spatrick #define OBJCPROPERTY(DERIVED, BASE) 584e5dd7070Spatrick #define OBJCPROPERTYIMPL(DERIVED, BASE) 585e5dd7070Spatrick #define EMPTY(DERIVED, BASE) 586e5dd7070Spatrick #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE) 587e5dd7070Spatrick 588e5dd7070Spatrick // Decls which use special-case instantiation code. 589e5dd7070Spatrick #define BLOCK(DERIVED, BASE) 590e5dd7070Spatrick #define CAPTURED(DERIVED, BASE) 591e5dd7070Spatrick #define IMPLICITPARAM(DERIVED, BASE) 592e5dd7070Spatrick 593e5dd7070Spatrick #include "clang/AST/DeclNodes.inc" 594e5dd7070Spatrick 595e5dd7070Spatrick enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual }; 596e5dd7070Spatrick 597e5dd7070Spatrick void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T, 598e5dd7070Spatrick TypeSourceInfo *&TInfo, 599e5dd7070Spatrick DeclarationNameInfo &NameInfo); 600e5dd7070Spatrick 601e5dd7070Spatrick // A few supplemental visitor functions. 602e5dd7070Spatrick Decl *VisitCXXMethodDecl(CXXMethodDecl *D, 603e5dd7070Spatrick TemplateParameterList *TemplateParams, 604*12c85518Srobert std::optional<const ASTTemplateArgumentListInfo *> 605*12c85518Srobert ClassScopeSpecializationArgs = std::nullopt, 606e5dd7070Spatrick RewriteKind RK = RewriteKind::None); 607e5dd7070Spatrick Decl *VisitFunctionDecl(FunctionDecl *D, 608e5dd7070Spatrick TemplateParameterList *TemplateParams, 609e5dd7070Spatrick RewriteKind RK = RewriteKind::None); 610e5dd7070Spatrick Decl *VisitDecl(Decl *D); 611e5dd7070Spatrick Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, 612e5dd7070Spatrick ArrayRef<BindingDecl *> *Bindings = nullptr); 613a9ac8606Spatrick Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst, 614a9ac8606Spatrick LookupResult *Lookup); 615e5dd7070Spatrick 616e5dd7070Spatrick // Enable late instantiation of attributes. Late instantiated attributes 617e5dd7070Spatrick // will be stored in LA. enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec * LA)618e5dd7070Spatrick void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) { 619e5dd7070Spatrick LateAttrs = LA; 620e5dd7070Spatrick StartingScope = SemaRef.CurrentInstantiationScope; 621e5dd7070Spatrick } 622e5dd7070Spatrick 623e5dd7070Spatrick // Disable late instantiation of attributes. disableLateAttributeInstantiation()624e5dd7070Spatrick void disableLateAttributeInstantiation() { 625e5dd7070Spatrick LateAttrs = nullptr; 626e5dd7070Spatrick StartingScope = nullptr; 627e5dd7070Spatrick } 628e5dd7070Spatrick getStartingScope()629e5dd7070Spatrick LocalInstantiationScope *getStartingScope() const { return StartingScope; } 630e5dd7070Spatrick 631e5dd7070Spatrick using delayed_partial_spec_iterator = SmallVectorImpl<std::pair< 632e5dd7070Spatrick ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator; 633e5dd7070Spatrick 634e5dd7070Spatrick using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair< 635e5dd7070Spatrick VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator; 636e5dd7070Spatrick 637e5dd7070Spatrick /// Return an iterator to the beginning of the set of 638e5dd7070Spatrick /// "delayed" partial specializations, which must be passed to 639e5dd7070Spatrick /// InstantiateClassTemplatePartialSpecialization once the class 640e5dd7070Spatrick /// definition has been completed. delayed_partial_spec_begin()641e5dd7070Spatrick delayed_partial_spec_iterator delayed_partial_spec_begin() { 642e5dd7070Spatrick return OutOfLinePartialSpecs.begin(); 643e5dd7070Spatrick } 644e5dd7070Spatrick delayed_var_partial_spec_begin()645e5dd7070Spatrick delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() { 646e5dd7070Spatrick return OutOfLineVarPartialSpecs.begin(); 647e5dd7070Spatrick } 648e5dd7070Spatrick 649e5dd7070Spatrick /// Return an iterator to the end of the set of 650e5dd7070Spatrick /// "delayed" partial specializations, which must be passed to 651e5dd7070Spatrick /// InstantiateClassTemplatePartialSpecialization once the class 652e5dd7070Spatrick /// definition has been completed. delayed_partial_spec_end()653e5dd7070Spatrick delayed_partial_spec_iterator delayed_partial_spec_end() { 654e5dd7070Spatrick return OutOfLinePartialSpecs.end(); 655e5dd7070Spatrick } 656e5dd7070Spatrick delayed_var_partial_spec_end()657e5dd7070Spatrick delayed_var_partial_spec_iterator delayed_var_partial_spec_end() { 658e5dd7070Spatrick return OutOfLineVarPartialSpecs.end(); 659e5dd7070Spatrick } 660e5dd7070Spatrick 661e5dd7070Spatrick // Helper functions for instantiating methods. 662e5dd7070Spatrick TypeSourceInfo *SubstFunctionType(FunctionDecl *D, 663e5dd7070Spatrick SmallVectorImpl<ParmVarDecl *> &Params); 664e5dd7070Spatrick bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); 665e5dd7070Spatrick bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); 666e5dd7070Spatrick 667e5dd7070Spatrick bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl); 668e5dd7070Spatrick 669e5dd7070Spatrick TemplateParameterList * 670e5dd7070Spatrick SubstTemplateParams(TemplateParameterList *List); 671e5dd7070Spatrick 672e5dd7070Spatrick bool SubstQualifier(const DeclaratorDecl *OldDecl, 673e5dd7070Spatrick DeclaratorDecl *NewDecl); 674e5dd7070Spatrick bool SubstQualifier(const TagDecl *OldDecl, 675e5dd7070Spatrick TagDecl *NewDecl); 676e5dd7070Spatrick 677e5dd7070Spatrick Decl *VisitVarTemplateSpecializationDecl( 678a9ac8606Spatrick VarTemplateDecl *VarTemplate, VarDecl *FromVar, 679e5dd7070Spatrick const TemplateArgumentListInfo &TemplateArgsInfo, 680e5dd7070Spatrick ArrayRef<TemplateArgument> Converted, 681e5dd7070Spatrick VarTemplateSpecializationDecl *PrevDecl = nullptr); 682e5dd7070Spatrick 683e5dd7070Spatrick Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); 684e5dd7070Spatrick ClassTemplatePartialSpecializationDecl * 685e5dd7070Spatrick InstantiateClassTemplatePartialSpecialization( 686e5dd7070Spatrick ClassTemplateDecl *ClassTemplate, 687e5dd7070Spatrick ClassTemplatePartialSpecializationDecl *PartialSpec); 688e5dd7070Spatrick VarTemplatePartialSpecializationDecl * 689e5dd7070Spatrick InstantiateVarTemplatePartialSpecialization( 690e5dd7070Spatrick VarTemplateDecl *VarTemplate, 691e5dd7070Spatrick VarTemplatePartialSpecializationDecl *PartialSpec); 692e5dd7070Spatrick void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern); 693e5dd7070Spatrick 694e5dd7070Spatrick private: 695e5dd7070Spatrick template<typename T> 696e5dd7070Spatrick Decl *instantiateUnresolvedUsingDecl(T *D, 697e5dd7070Spatrick bool InstantiatingPackElement = false); 698e5dd7070Spatrick }; 699e5dd7070Spatrick 700e5dd7070Spatrick } // namespace clang 701e5dd7070Spatrick 702e5dd7070Spatrick #endif // LLVM_CLANG_SEMA_TEMPLATE_H 703