10b57cec5SDimitry Andric //===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
70b57cec5SDimitry Andric //
80b57cec5SDimitry Andric // This file provides types used in the semantic analysis of C++ templates.
90b57cec5SDimitry Andric //
100b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #ifndef LLVM_CLANG_SEMA_TEMPLATE_H
130b57cec5SDimitry Andric #define LLVM_CLANG_SEMA_TEMPLATE_H
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclVisitor.h"
170b57cec5SDimitry Andric #include "clang/AST/TemplateBase.h"
180b57cec5SDimitry Andric #include "clang/AST/Type.h"
190b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
200b57cec5SDimitry Andric #include "clang/Sema/Sema.h"
210b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
220b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
230b57cec5SDimitry Andric #include "llvm/ADT/PointerUnion.h"
240b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
250b57cec5SDimitry Andric #include <cassert>
26bdd1243dSDimitry Andric #include <optional>
270b57cec5SDimitry Andric #include <utility>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric namespace clang {
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric class ASTContext;
320b57cec5SDimitry Andric class BindingDecl;
330b57cec5SDimitry Andric class CXXMethodDecl;
340b57cec5SDimitry Andric class Decl;
350b57cec5SDimitry Andric class DeclaratorDecl;
360b57cec5SDimitry Andric class DeclContext;
370b57cec5SDimitry Andric class EnumDecl;
380b57cec5SDimitry Andric class FunctionDecl;
390b57cec5SDimitry Andric class NamedDecl;
400b57cec5SDimitry Andric class ParmVarDecl;
410b57cec5SDimitry Andric class TagDecl;
420b57cec5SDimitry Andric class TypedefNameDecl;
430b57cec5SDimitry Andric class TypeSourceInfo;
440b57cec5SDimitry Andric class VarDecl;
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric /// The kind of template substitution being performed.
475ffd83dbSDimitry Andric enum class TemplateSubstitutionKind : char {
485ffd83dbSDimitry Andric   /// We are substituting template parameters for template arguments in order
495ffd83dbSDimitry Andric   /// to form a template specialization.
505ffd83dbSDimitry Andric   Specialization,
515ffd83dbSDimitry Andric   /// We are substituting template parameters for (typically) other template
525ffd83dbSDimitry Andric   /// parameters in order to rewrite a declaration as a different declaration
535ffd83dbSDimitry Andric   /// (for example, when forming a deduction guide from a constructor).
545ffd83dbSDimitry Andric   Rewrite,
555ffd83dbSDimitry Andric };
565ffd83dbSDimitry Andric 
570b57cec5SDimitry Andric   /// Data structure that captures multiple levels of template argument
580b57cec5SDimitry Andric   /// lists for use in template instantiation.
590b57cec5SDimitry Andric   ///
600b57cec5SDimitry Andric   /// Multiple levels of template arguments occur when instantiating the
610b57cec5SDimitry Andric   /// definitions of member templates. For example:
620b57cec5SDimitry Andric   ///
630b57cec5SDimitry Andric   /// \code
640b57cec5SDimitry Andric   /// template<typename T>
650b57cec5SDimitry Andric   /// struct X {
660b57cec5SDimitry Andric   ///   template<T Value>
670b57cec5SDimitry Andric   ///   struct Y {
680b57cec5SDimitry Andric   ///     void f();
690b57cec5SDimitry Andric   ///   };
700b57cec5SDimitry Andric   /// };
710b57cec5SDimitry Andric   /// \endcode
720b57cec5SDimitry Andric   ///
730b57cec5SDimitry Andric   /// When instantiating X<int>::Y<17>::f, the multi-level template argument
740b57cec5SDimitry Andric   /// list will contain a template argument list (int) at depth 0 and a
750b57cec5SDimitry Andric   /// template argument list (17) at depth 1.
760b57cec5SDimitry Andric   class MultiLevelTemplateArgumentList {
770b57cec5SDimitry Andric     /// The template argument list at a certain template depth
78bdd1243dSDimitry Andric 
790b57cec5SDimitry Andric     using ArgList = ArrayRef<TemplateArgument>;
80bdd1243dSDimitry Andric     struct ArgumentListLevel {
81bdd1243dSDimitry Andric       llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
82bdd1243dSDimitry Andric       ArgList Args;
83bdd1243dSDimitry Andric     };
84bdd1243dSDimitry Andric     using ContainerType = SmallVector<ArgumentListLevel, 4>;
85bdd1243dSDimitry Andric 
86bdd1243dSDimitry Andric     using ArgListsIterator = ContainerType::iterator;
87bdd1243dSDimitry Andric     using ConstArgListsIterator = ContainerType::const_iterator;
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     /// The template argument lists, stored from the innermost template
900b57cec5SDimitry Andric     /// argument list (first) to the outermost template argument list (last).
91bdd1243dSDimitry Andric     ContainerType TemplateArgumentLists;
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric     /// The number of outer levels of template arguments that are not
940b57cec5SDimitry Andric     /// being substituted.
950b57cec5SDimitry Andric     unsigned NumRetainedOuterLevels = 0;
960b57cec5SDimitry Andric 
975ffd83dbSDimitry Andric     /// The kind of substitution described by this argument list.
985ffd83dbSDimitry Andric     TemplateSubstitutionKind Kind = TemplateSubstitutionKind::Specialization;
995ffd83dbSDimitry Andric 
1000b57cec5SDimitry Andric   public:
1010b57cec5SDimitry Andric     /// Construct an empty set of template argument lists.
1020b57cec5SDimitry Andric     MultiLevelTemplateArgumentList() = default;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     /// Construct a single-level template argument list.
MultiLevelTemplateArgumentList(Decl * D,ArgList Args,bool Final)105bdd1243dSDimitry Andric     MultiLevelTemplateArgumentList(Decl *D, ArgList Args, bool Final) {
106bdd1243dSDimitry Andric       addOuterTemplateArguments(D, Args, Final);
1070b57cec5SDimitry Andric     }
1080b57cec5SDimitry Andric 
setKind(TemplateSubstitutionKind K)1095ffd83dbSDimitry Andric     void setKind(TemplateSubstitutionKind K) { Kind = K; }
1105ffd83dbSDimitry Andric 
1115ffd83dbSDimitry Andric     /// Determine the kind of template substitution being performed.
getKind()1125ffd83dbSDimitry Andric     TemplateSubstitutionKind getKind() const { return Kind; }
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric     /// Determine whether we are rewriting template parameters rather than
1155ffd83dbSDimitry Andric     /// substituting for them. If so, we should not leave references to the
1165ffd83dbSDimitry Andric     /// original template parameters behind.
isRewrite()1175ffd83dbSDimitry Andric     bool isRewrite() const {
1185ffd83dbSDimitry Andric       return Kind == TemplateSubstitutionKind::Rewrite;
1195ffd83dbSDimitry Andric     }
1205ffd83dbSDimitry Andric 
1210b57cec5SDimitry Andric     /// Determine the number of levels in this template argument
1220b57cec5SDimitry Andric     /// list.
getNumLevels()1230b57cec5SDimitry Andric     unsigned getNumLevels() const {
1240b57cec5SDimitry Andric       return TemplateArgumentLists.size() + NumRetainedOuterLevels;
1250b57cec5SDimitry Andric     }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric     /// Determine the number of substituted levels in this template
1280b57cec5SDimitry Andric     /// argument list.
getNumSubstitutedLevels()1290b57cec5SDimitry Andric     unsigned getNumSubstitutedLevels() const {
1300b57cec5SDimitry Andric       return TemplateArgumentLists.size();
1310b57cec5SDimitry Andric     }
1320b57cec5SDimitry Andric 
133972a253aSDimitry Andric     // Determine the number of substituted args at 'Depth'.
getNumSubsitutedArgs(unsigned Depth)134972a253aSDimitry Andric     unsigned getNumSubsitutedArgs(unsigned Depth) const {
135972a253aSDimitry Andric       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
136bdd1243dSDimitry Andric       return TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size();
137972a253aSDimitry Andric     }
138972a253aSDimitry Andric 
getNumRetainedOuterLevels()1395ffd83dbSDimitry Andric     unsigned getNumRetainedOuterLevels() const {
1405ffd83dbSDimitry Andric       return NumRetainedOuterLevels;
1415ffd83dbSDimitry Andric     }
1425ffd83dbSDimitry Andric 
143cd675bb6SDimitry Andric     /// Determine how many of the \p OldDepth outermost template parameter
144cd675bb6SDimitry Andric     /// lists would be removed by substituting these arguments.
getNewDepth(unsigned OldDepth)145cd675bb6SDimitry Andric     unsigned getNewDepth(unsigned OldDepth) const {
146cd675bb6SDimitry Andric       if (OldDepth < NumRetainedOuterLevels)
147cd675bb6SDimitry Andric         return OldDepth;
148cd675bb6SDimitry Andric       if (OldDepth < getNumLevels())
149cd675bb6SDimitry Andric         return NumRetainedOuterLevels;
150cd675bb6SDimitry Andric       return OldDepth - TemplateArgumentLists.size();
151cd675bb6SDimitry Andric     }
152cd675bb6SDimitry Andric 
1530b57cec5SDimitry Andric     /// Retrieve the template argument at a given depth and index.
operator()1540b57cec5SDimitry Andric     const TemplateArgument &operator()(unsigned Depth, unsigned Index) const {
1550b57cec5SDimitry Andric       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
156bdd1243dSDimitry Andric       assert(Index <
157bdd1243dSDimitry Andric              TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
158bdd1243dSDimitry Andric       return TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index];
159bdd1243dSDimitry Andric     }
160bdd1243dSDimitry Andric 
161bdd1243dSDimitry Andric     /// A template-like entity which owns the whole pattern being substituted.
162bdd1243dSDimitry Andric     /// This will usually own a set of template parameters, or in some
163bdd1243dSDimitry Andric     /// cases might even be a template parameter itself.
getAssociatedDecl(unsigned Depth)164bdd1243dSDimitry Andric     std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
165bdd1243dSDimitry Andric       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
166bdd1243dSDimitry Andric       auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
167bdd1243dSDimitry Andric                     .AssociatedDeclAndFinal;
168bdd1243dSDimitry Andric       return {AD.getPointer(), AD.getInt()};
1690b57cec5SDimitry Andric     }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric     /// Determine whether there is a non-NULL template argument at the
1720b57cec5SDimitry Andric     /// given depth and index.
1730b57cec5SDimitry Andric     ///
1740b57cec5SDimitry Andric     /// There must exist a template argument list at the given depth.
hasTemplateArgument(unsigned Depth,unsigned Index)1750b57cec5SDimitry Andric     bool hasTemplateArgument(unsigned Depth, unsigned Index) const {
1760b57cec5SDimitry Andric       assert(Depth < getNumLevels());
1770b57cec5SDimitry Andric 
1780b57cec5SDimitry Andric       if (Depth < NumRetainedOuterLevels)
1790b57cec5SDimitry Andric         return false;
1800b57cec5SDimitry Andric 
181bdd1243dSDimitry Andric       if (Index >=
182bdd1243dSDimitry Andric           TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size())
1830b57cec5SDimitry Andric         return false;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric       return !(*this)(Depth, Index).isNull();
1860b57cec5SDimitry Andric     }
1870b57cec5SDimitry Andric 
isAnyArgInstantiationDependent()188972a253aSDimitry Andric     bool isAnyArgInstantiationDependent() const {
189bdd1243dSDimitry Andric       for (ArgumentListLevel ListLevel : TemplateArgumentLists)
190bdd1243dSDimitry Andric         for (const TemplateArgument &TA : ListLevel.Args)
191972a253aSDimitry Andric           if (TA.isInstantiationDependent())
192972a253aSDimitry Andric             return true;
193972a253aSDimitry Andric       return false;
194972a253aSDimitry Andric     }
195972a253aSDimitry Andric 
1960b57cec5SDimitry Andric     /// Clear out a specific template argument.
setArgument(unsigned Depth,unsigned Index,TemplateArgument Arg)1970b57cec5SDimitry Andric     void setArgument(unsigned Depth, unsigned Index,
1980b57cec5SDimitry Andric                      TemplateArgument Arg) {
1990b57cec5SDimitry Andric       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
200bdd1243dSDimitry Andric       assert(Index <
201bdd1243dSDimitry Andric              TemplateArgumentLists[getNumLevels() - Depth - 1].Args.size());
2020b57cec5SDimitry Andric       const_cast<TemplateArgument &>(
203bdd1243dSDimitry Andric           TemplateArgumentLists[getNumLevels() - Depth - 1].Args[Index]) = Arg;
2040b57cec5SDimitry Andric     }
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     /// Add a new outmost level to the multi-level template argument
2070b57cec5SDimitry Andric     /// list.
208bdd1243dSDimitry Andric     /// A 'Final' substitution means that Subst* nodes won't be built
209bdd1243dSDimitry Andric     /// for the replacements.
addOuterTemplateArguments(Decl * AssociatedDecl,ArgList Args,bool Final)210bdd1243dSDimitry Andric     void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
211bdd1243dSDimitry Andric                                    bool Final) {
212bdd1243dSDimitry Andric       assert(!NumRetainedOuterLevels &&
213bdd1243dSDimitry Andric              "substituted args outside retained args?");
214bdd1243dSDimitry Andric       assert(getKind() == TemplateSubstitutionKind::Specialization);
215bdd1243dSDimitry Andric       TemplateArgumentLists.push_back(
2165f757f3fSDimitry Andric           {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
2175f757f3fSDimitry Andric             Final},
2185f757f3fSDimitry Andric            Args});
219bdd1243dSDimitry Andric     }
220bdd1243dSDimitry Andric 
addOuterTemplateArguments(ArgList Args)2210b57cec5SDimitry Andric     void addOuterTemplateArguments(ArgList Args) {
2220b57cec5SDimitry Andric       assert(!NumRetainedOuterLevels &&
2230b57cec5SDimitry Andric              "substituted args outside retained args?");
224bdd1243dSDimitry Andric       assert(getKind() == TemplateSubstitutionKind::Rewrite);
225bdd1243dSDimitry Andric       TemplateArgumentLists.push_back({{}, Args});
226bdd1243dSDimitry Andric     }
227bdd1243dSDimitry Andric 
addOuterTemplateArguments(std::nullopt_t)228bdd1243dSDimitry Andric     void addOuterTemplateArguments(std::nullopt_t) {
229bdd1243dSDimitry Andric       assert(!NumRetainedOuterLevels &&
230bdd1243dSDimitry Andric              "substituted args outside retained args?");
231bdd1243dSDimitry Andric       TemplateArgumentLists.push_back({});
2320b57cec5SDimitry Andric     }
2330b57cec5SDimitry Andric 
234972a253aSDimitry Andric     /// Replaces the current 'innermost' level with the provided argument list.
235972a253aSDimitry Andric     /// This is useful for type deduction cases where we need to get the entire
236972a253aSDimitry Andric     /// list from the AST, but then add the deduced innermost list.
replaceInnermostTemplateArguments(Decl * AssociatedDecl,ArgList Args)23706c3fb27SDimitry Andric     void replaceInnermostTemplateArguments(Decl *AssociatedDecl, ArgList Args) {
23806c3fb27SDimitry Andric       assert((!TemplateArgumentLists.empty() || NumRetainedOuterLevels) &&
23906c3fb27SDimitry Andric              "Replacing in an empty list?");
24006c3fb27SDimitry Andric 
24106c3fb27SDimitry Andric       if (!TemplateArgumentLists.empty()) {
24206c3fb27SDimitry Andric         assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
24306c3fb27SDimitry Andric                 TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
24406c3fb27SDimitry Andric                     AssociatedDecl) &&
24506c3fb27SDimitry Andric                "Trying to change incorrect declaration?");
246bdd1243dSDimitry Andric         TemplateArgumentLists[0].Args = Args;
24706c3fb27SDimitry Andric       } else {
24806c3fb27SDimitry Andric         --NumRetainedOuterLevels;
24906c3fb27SDimitry Andric         TemplateArgumentLists.push_back(
25006c3fb27SDimitry Andric             {{AssociatedDecl, /*Final=*/false}, Args});
25106c3fb27SDimitry Andric       }
252972a253aSDimitry Andric     }
253972a253aSDimitry Andric 
2540b57cec5SDimitry Andric     /// Add an outermost level that we are not substituting. We have no
2550b57cec5SDimitry Andric     /// arguments at this level, and do not remove it from the depth of inner
2560b57cec5SDimitry Andric     /// template parameters that we instantiate.
addOuterRetainedLevel()2570b57cec5SDimitry Andric     void addOuterRetainedLevel() {
2580b57cec5SDimitry Andric       ++NumRetainedOuterLevels;
2590b57cec5SDimitry Andric     }
addOuterRetainedLevels(unsigned Num)2605ffd83dbSDimitry Andric     void addOuterRetainedLevels(unsigned Num) {
2615ffd83dbSDimitry Andric       NumRetainedOuterLevels += Num;
2625ffd83dbSDimitry Andric     }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric     /// Retrieve the innermost template argument list.
getInnermost()2650b57cec5SDimitry Andric     const ArgList &getInnermost() const {
266bdd1243dSDimitry Andric       return TemplateArgumentLists.front().Args;
2670b57cec5SDimitry Andric     }
268972a253aSDimitry Andric     /// Retrieve the outermost template argument list.
getOutermost()269972a253aSDimitry Andric     const ArgList &getOutermost() const {
270bdd1243dSDimitry Andric       return TemplateArgumentLists.back().Args;
271972a253aSDimitry Andric     }
begin()272972a253aSDimitry Andric     ArgListsIterator begin() { return TemplateArgumentLists.begin(); }
begin()273972a253aSDimitry Andric     ConstArgListsIterator begin() const {
274972a253aSDimitry Andric       return TemplateArgumentLists.begin();
275972a253aSDimitry Andric     }
end()276972a253aSDimitry Andric     ArgListsIterator end() { return TemplateArgumentLists.end(); }
end()277972a253aSDimitry Andric     ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
27806c3fb27SDimitry Andric 
dump()27906c3fb27SDimitry Andric     LLVM_DUMP_METHOD void dump() const {
28006c3fb27SDimitry Andric       LangOptions LO;
28106c3fb27SDimitry Andric       LO.CPlusPlus = true;
28206c3fb27SDimitry Andric       LO.Bool = true;
28306c3fb27SDimitry Andric       PrintingPolicy PP(LO);
28406c3fb27SDimitry Andric       llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
28506c3fb27SDimitry Andric                    << "\n";
28606c3fb27SDimitry Andric       for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
28706c3fb27SDimitry Andric            ++Depth) {
28806c3fb27SDimitry Andric         llvm::errs() << Depth << ": ";
28906c3fb27SDimitry Andric         printTemplateArgumentList(
29006c3fb27SDimitry Andric             llvm::errs(),
29106c3fb27SDimitry Andric             TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
29206c3fb27SDimitry Andric         llvm::errs() << "\n";
29306c3fb27SDimitry Andric       }
29406c3fb27SDimitry Andric     }
2950b57cec5SDimitry Andric   };
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   /// The context in which partial ordering of function templates occurs.
2980b57cec5SDimitry Andric   enum TPOC {
2990b57cec5SDimitry Andric     /// Partial ordering of function templates for a function call.
3000b57cec5SDimitry Andric     TPOC_Call,
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric     /// Partial ordering of function templates for a call to a
3030b57cec5SDimitry Andric     /// conversion function.
3040b57cec5SDimitry Andric     TPOC_Conversion,
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric     /// Partial ordering of function templates in other contexts, e.g.,
3070b57cec5SDimitry Andric     /// taking the address of a function template or matching a function
3080b57cec5SDimitry Andric     /// template specialization to a function template.
3090b57cec5SDimitry Andric     TPOC_Other
3100b57cec5SDimitry Andric   };
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   // This is lame but unavoidable in a world without forward
3130b57cec5SDimitry Andric   // declarations of enums.  The alternatives are to either pollute
3140b57cec5SDimitry Andric   // Sema.h (by including this file) or sacrifice type safety (by
3150b57cec5SDimitry Andric   // making Sema.h declare things as enums).
3160b57cec5SDimitry Andric   class TemplatePartialOrderingContext {
3170b57cec5SDimitry Andric     TPOC Value;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   public:
TemplatePartialOrderingContext(TPOC Value)3200b57cec5SDimitry Andric     TemplatePartialOrderingContext(TPOC Value) : Value(Value) {}
3210b57cec5SDimitry Andric 
TPOC()3220b57cec5SDimitry Andric     operator TPOC() const { return Value; }
3230b57cec5SDimitry Andric   };
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Captures a template argument whose value has been deduced
3260b57cec5SDimitry Andric   /// via c++ template argument deduction.
3270b57cec5SDimitry Andric   class DeducedTemplateArgument : public TemplateArgument {
3280b57cec5SDimitry Andric     /// For a non-type template argument, whether the value was
3290b57cec5SDimitry Andric     /// deduced from an array bound.
3300b57cec5SDimitry Andric     bool DeducedFromArrayBound = false;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   public:
3330b57cec5SDimitry Andric     DeducedTemplateArgument() = default;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric     DeducedTemplateArgument(const TemplateArgument &Arg,
3360b57cec5SDimitry Andric                             bool DeducedFromArrayBound = false)
TemplateArgument(Arg)3370b57cec5SDimitry Andric         : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {}
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     /// Construct an integral non-type template argument that
3400b57cec5SDimitry Andric     /// has been deduced, possibly from an array bound.
DeducedTemplateArgument(ASTContext & Ctx,const llvm::APSInt & Value,QualType ValueType,bool DeducedFromArrayBound)3410b57cec5SDimitry Andric     DeducedTemplateArgument(ASTContext &Ctx,
3420b57cec5SDimitry Andric                             const llvm::APSInt &Value,
3430b57cec5SDimitry Andric                             QualType ValueType,
3440b57cec5SDimitry Andric                             bool DeducedFromArrayBound)
3450b57cec5SDimitry Andric         : TemplateArgument(Ctx, Value, ValueType),
3460b57cec5SDimitry Andric           DeducedFromArrayBound(DeducedFromArrayBound) {}
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric     /// For a non-type template argument, determine whether the
3490b57cec5SDimitry Andric     /// template argument was deduced from an array bound.
wasDeducedFromArrayBound()3500b57cec5SDimitry Andric     bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; }
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric     /// Specify whether the given non-type template argument
3530b57cec5SDimitry Andric     /// was deduced from an array bound.
setDeducedFromArrayBound(bool Deduced)3540b57cec5SDimitry Andric     void setDeducedFromArrayBound(bool Deduced) {
3550b57cec5SDimitry Andric       DeducedFromArrayBound = Deduced;
3560b57cec5SDimitry Andric     }
3570b57cec5SDimitry Andric   };
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric   /// A stack-allocated class that identifies which local
3600b57cec5SDimitry Andric   /// variable declaration instantiations are present in this scope.
3610b57cec5SDimitry Andric   ///
3620b57cec5SDimitry Andric   /// A new instance of this class type will be created whenever we
3630b57cec5SDimitry Andric   /// instantiate a new function declaration, which will have its own
3640b57cec5SDimitry Andric   /// set of parameter declarations.
3650b57cec5SDimitry Andric   class LocalInstantiationScope {
3660b57cec5SDimitry Andric   public:
3670b57cec5SDimitry Andric     /// A set of declarations.
3680b57cec5SDimitry Andric     using DeclArgumentPack = SmallVector<VarDecl *, 4>;
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   private:
3710b57cec5SDimitry Andric     /// Reference to the semantic analysis that is performing
3720b57cec5SDimitry Andric     /// this template instantiation.
3730b57cec5SDimitry Andric     Sema &SemaRef;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     using LocalDeclsMap =
3760b57cec5SDimitry Andric         llvm::SmallDenseMap<const Decl *,
3770b57cec5SDimitry Andric                             llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric     /// A mapping from local declarations that occur
3800b57cec5SDimitry Andric     /// within a template to their instantiations.
3810b57cec5SDimitry Andric     ///
3820b57cec5SDimitry Andric     /// This mapping is used during instantiation to keep track of,
3830b57cec5SDimitry Andric     /// e.g., function parameter and variable declarations. For example,
3840b57cec5SDimitry Andric     /// given:
3850b57cec5SDimitry Andric     ///
3860b57cec5SDimitry Andric     /// \code
3870b57cec5SDimitry Andric     ///   template<typename T> T add(T x, T y) { return x + y; }
3880b57cec5SDimitry Andric     /// \endcode
3890b57cec5SDimitry Andric     ///
3900b57cec5SDimitry Andric     /// when we instantiate add<int>, we will introduce a mapping from
3910b57cec5SDimitry Andric     /// the ParmVarDecl for 'x' that occurs in the template to the
3920b57cec5SDimitry Andric     /// instantiated ParmVarDecl for 'x'.
3930b57cec5SDimitry Andric     ///
3940b57cec5SDimitry Andric     /// For a parameter pack, the local instantiation scope may contain a
3950b57cec5SDimitry Andric     /// set of instantiated parameters. This is stored as a DeclArgumentPack
3960b57cec5SDimitry Andric     /// pointer.
3970b57cec5SDimitry Andric     LocalDeclsMap LocalDecls;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric     /// The set of argument packs we've allocated.
4000b57cec5SDimitry Andric     SmallVector<DeclArgumentPack *, 1> ArgumentPacks;
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric     /// The outer scope, which contains local variable
4030b57cec5SDimitry Andric     /// definitions from some other instantiation (that may not be
4040b57cec5SDimitry Andric     /// relevant to this particular scope).
4050b57cec5SDimitry Andric     LocalInstantiationScope *Outer;
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric     /// Whether we have already exited this scope.
4080b57cec5SDimitry Andric     bool Exited = false;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric     /// Whether to combine this scope with the outer scope, such that
4110b57cec5SDimitry Andric     /// lookup will search our outer scope.
4120b57cec5SDimitry Andric     bool CombineWithOuterScope;
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric     /// If non-NULL, the template parameter pack that has been
4150b57cec5SDimitry Andric     /// partially substituted per C++0x [temp.arg.explicit]p9.
4160b57cec5SDimitry Andric     NamedDecl *PartiallySubstitutedPack = nullptr;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric     /// If \c PartiallySubstitutedPack is non-null, the set of
4190b57cec5SDimitry Andric     /// explicitly-specified template arguments in that pack.
4200b57cec5SDimitry Andric     const TemplateArgument *ArgsInPartiallySubstitutedPack;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     /// If \c PartiallySubstitutedPack, the number of
4230b57cec5SDimitry Andric     /// explicitly-specified template arguments in
4240b57cec5SDimitry Andric     /// ArgsInPartiallySubstitutedPack.
4250b57cec5SDimitry Andric     unsigned NumArgsInPartiallySubstitutedPack;
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   public:
4280b57cec5SDimitry Andric     LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false)
SemaRef(SemaRef)4290b57cec5SDimitry Andric         : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope),
4300b57cec5SDimitry Andric           CombineWithOuterScope(CombineWithOuterScope) {
4310b57cec5SDimitry Andric       SemaRef.CurrentInstantiationScope = this;
4320b57cec5SDimitry Andric     }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric     LocalInstantiationScope(const LocalInstantiationScope &) = delete;
4350b57cec5SDimitry Andric     LocalInstantiationScope &
4360b57cec5SDimitry Andric     operator=(const LocalInstantiationScope &) = delete;
4370b57cec5SDimitry Andric 
~LocalInstantiationScope()4380b57cec5SDimitry Andric     ~LocalInstantiationScope() {
4390b57cec5SDimitry Andric       Exit();
4400b57cec5SDimitry Andric     }
4410b57cec5SDimitry Andric 
getSema()4420b57cec5SDimitry Andric     const Sema &getSema() const { return SemaRef; }
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     /// Exit this local instantiation scope early.
Exit()4450b57cec5SDimitry Andric     void Exit() {
4460b57cec5SDimitry Andric       if (Exited)
4470b57cec5SDimitry Andric         return;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric       for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I)
4500b57cec5SDimitry Andric         delete ArgumentPacks[I];
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric       SemaRef.CurrentInstantiationScope = Outer;
4530b57cec5SDimitry Andric       Exited = true;
4540b57cec5SDimitry Andric     }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric     /// Clone this scope, and all outer scopes, down to the given
4570b57cec5SDimitry Andric     /// outermost scope.
cloneScopes(LocalInstantiationScope * Outermost)4580b57cec5SDimitry Andric     LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) {
4590b57cec5SDimitry Andric       if (this == Outermost) return this;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric       // Save the current scope from SemaRef since the LocalInstantiationScope
4620b57cec5SDimitry Andric       // will overwrite it on construction
4630b57cec5SDimitry Andric       LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric       LocalInstantiationScope *newScope =
4660b57cec5SDimitry Andric         new LocalInstantiationScope(SemaRef, CombineWithOuterScope);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric       newScope->Outer = nullptr;
4690b57cec5SDimitry Andric       if (Outer)
4700b57cec5SDimitry Andric         newScope->Outer = Outer->cloneScopes(Outermost);
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric       newScope->PartiallySubstitutedPack = PartiallySubstitutedPack;
4730b57cec5SDimitry Andric       newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack;
4740b57cec5SDimitry Andric       newScope->NumArgsInPartiallySubstitutedPack =
4750b57cec5SDimitry Andric         NumArgsInPartiallySubstitutedPack;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric       for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end();
4780b57cec5SDimitry Andric            I != E; ++I) {
4790b57cec5SDimitry Andric         const Decl *D = I->first;
4800b57cec5SDimitry Andric         llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored =
4810b57cec5SDimitry Andric           newScope->LocalDecls[D];
4820b57cec5SDimitry Andric         if (I->second.is<Decl *>()) {
4830b57cec5SDimitry Andric           Stored = I->second.get<Decl *>();
4840b57cec5SDimitry Andric         } else {
4850b57cec5SDimitry Andric           DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>();
4860b57cec5SDimitry Andric           DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack);
4870b57cec5SDimitry Andric           Stored = NewPack;
4880b57cec5SDimitry Andric           newScope->ArgumentPacks.push_back(NewPack);
4890b57cec5SDimitry Andric         }
4900b57cec5SDimitry Andric       }
4910b57cec5SDimitry Andric       // Restore the saved scope to SemaRef
4920b57cec5SDimitry Andric       SemaRef.CurrentInstantiationScope = oldScope;
4930b57cec5SDimitry Andric       return newScope;
4940b57cec5SDimitry Andric     }
4950b57cec5SDimitry Andric 
49681ad6265SDimitry Andric     /// deletes the given scope, and all outer scopes, down to the
4970b57cec5SDimitry Andric     /// given outermost scope.
deleteScopes(LocalInstantiationScope * Scope,LocalInstantiationScope * Outermost)4980b57cec5SDimitry Andric     static void deleteScopes(LocalInstantiationScope *Scope,
4990b57cec5SDimitry Andric                              LocalInstantiationScope *Outermost) {
5000b57cec5SDimitry Andric       while (Scope && Scope != Outermost) {
5010b57cec5SDimitry Andric         LocalInstantiationScope *Out = Scope->Outer;
5020b57cec5SDimitry Andric         delete Scope;
5030b57cec5SDimitry Andric         Scope = Out;
5040b57cec5SDimitry Andric       }
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric     /// Find the instantiation of the declaration D within the current
5080b57cec5SDimitry Andric     /// instantiation scope.
5090b57cec5SDimitry Andric     ///
5100b57cec5SDimitry Andric     /// \param D The declaration whose instantiation we are searching for.
5110b57cec5SDimitry Andric     ///
5120b57cec5SDimitry Andric     /// \returns A pointer to the declaration or argument pack of declarations
5130b57cec5SDimitry Andric     /// to which the declaration \c D is instantiated, if found. Otherwise,
5140b57cec5SDimitry Andric     /// returns NULL.
5150b57cec5SDimitry Andric     llvm::PointerUnion<Decl *, DeclArgumentPack *> *
5160b57cec5SDimitry Andric     findInstantiationOf(const Decl *D);
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric     void InstantiatedLocal(const Decl *D, Decl *Inst);
5190b57cec5SDimitry Andric     void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst);
5200b57cec5SDimitry Andric     void MakeInstantiatedLocalArgPack(const Decl *D);
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     /// Note that the given parameter pack has been partially substituted
5230b57cec5SDimitry Andric     /// via explicit specification of template arguments
5240b57cec5SDimitry Andric     /// (C++0x [temp.arg.explicit]p9).
5250b57cec5SDimitry Andric     ///
5260b57cec5SDimitry Andric     /// \param Pack The parameter pack, which will always be a template
5270b57cec5SDimitry Andric     /// parameter pack.
5280b57cec5SDimitry Andric     ///
5290b57cec5SDimitry Andric     /// \param ExplicitArgs The explicitly-specified template arguments provided
5300b57cec5SDimitry Andric     /// for this parameter pack.
5310b57cec5SDimitry Andric     ///
5320b57cec5SDimitry Andric     /// \param NumExplicitArgs The number of explicitly-specified template
5330b57cec5SDimitry Andric     /// arguments provided for this parameter pack.
5340b57cec5SDimitry Andric     void SetPartiallySubstitutedPack(NamedDecl *Pack,
5350b57cec5SDimitry Andric                                      const TemplateArgument *ExplicitArgs,
5360b57cec5SDimitry Andric                                      unsigned NumExplicitArgs);
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric     /// Reset the partially-substituted pack when it is no longer of
5390b57cec5SDimitry Andric     /// interest.
ResetPartiallySubstitutedPack()5400b57cec5SDimitry Andric     void ResetPartiallySubstitutedPack() {
5410b57cec5SDimitry Andric       assert(PartiallySubstitutedPack && "No partially-substituted pack");
5420b57cec5SDimitry Andric       PartiallySubstitutedPack = nullptr;
5430b57cec5SDimitry Andric       ArgsInPartiallySubstitutedPack = nullptr;
5440b57cec5SDimitry Andric       NumArgsInPartiallySubstitutedPack = 0;
5450b57cec5SDimitry Andric     }
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric     /// Retrieve the partially-substitued template parameter pack.
5480b57cec5SDimitry Andric     ///
5490b57cec5SDimitry Andric     /// If there is no partially-substituted parameter pack, returns NULL.
5500b57cec5SDimitry Andric     NamedDecl *
5510b57cec5SDimitry Andric     getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr,
5520b57cec5SDimitry Andric                                 unsigned *NumExplicitArgs = nullptr) const;
5535ffd83dbSDimitry Andric 
5545ffd83dbSDimitry Andric     /// Determine whether D is a pack expansion created in this scope.
5555ffd83dbSDimitry Andric     bool isLocalPackExpansion(const Decl *D);
5560b57cec5SDimitry Andric   };
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   class TemplateDeclInstantiator
5590b57cec5SDimitry Andric     : public DeclVisitor<TemplateDeclInstantiator, Decl *>
5600b57cec5SDimitry Andric   {
5610b57cec5SDimitry Andric     Sema &SemaRef;
5620b57cec5SDimitry Andric     Sema::ArgumentPackSubstitutionIndexRAII SubstIndex;
5630b57cec5SDimitry Andric     DeclContext *Owner;
5640b57cec5SDimitry Andric     const MultiLevelTemplateArgumentList &TemplateArgs;
5650b57cec5SDimitry Andric     Sema::LateInstantiatedAttrVec* LateAttrs = nullptr;
5660b57cec5SDimitry Andric     LocalInstantiationScope *StartingScope = nullptr;
5671db9f3b2SDimitry Andric     // Whether to evaluate the C++20 constraints or simply substitute into them.
568bdd1243dSDimitry Andric     bool EvaluateConstraints = true;
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric     /// A list of out-of-line class template partial
5710b57cec5SDimitry Andric     /// specializations that will need to be instantiated after the
5720b57cec5SDimitry Andric     /// enclosing class's instantiation is complete.
5730b57cec5SDimitry Andric     SmallVector<std::pair<ClassTemplateDecl *,
5740b57cec5SDimitry Andric                                 ClassTemplatePartialSpecializationDecl *>, 4>
5750b57cec5SDimitry Andric       OutOfLinePartialSpecs;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric     /// A list of out-of-line variable template partial
5780b57cec5SDimitry Andric     /// specializations that will need to be instantiated after the
5790b57cec5SDimitry Andric     /// enclosing variable's instantiation is complete.
5800b57cec5SDimitry Andric     /// FIXME: Verify that this is needed.
5810b57cec5SDimitry Andric     SmallVector<
5820b57cec5SDimitry Andric         std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4>
5830b57cec5SDimitry Andric     OutOfLineVarPartialSpecs;
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   public:
TemplateDeclInstantiator(Sema & SemaRef,DeclContext * Owner,const MultiLevelTemplateArgumentList & TemplateArgs)5860b57cec5SDimitry Andric     TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner,
5870b57cec5SDimitry Andric                              const MultiLevelTemplateArgumentList &TemplateArgs)
5880b57cec5SDimitry Andric         : SemaRef(SemaRef),
5890b57cec5SDimitry Andric           SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex),
5900b57cec5SDimitry Andric           Owner(Owner), TemplateArgs(TemplateArgs) {}
5910b57cec5SDimitry Andric 
setEvaluateConstraints(bool B)592bdd1243dSDimitry Andric     void setEvaluateConstraints(bool B) {
593bdd1243dSDimitry Andric       EvaluateConstraints = B;
594bdd1243dSDimitry Andric     }
getEvaluateConstraints()595bdd1243dSDimitry Andric     bool getEvaluateConstraints() {
596bdd1243dSDimitry Andric       return EvaluateConstraints;
597bdd1243dSDimitry Andric     }
598bdd1243dSDimitry Andric 
5990b57cec5SDimitry Andric // Define all the decl visitors using DeclNodes.inc
6000b57cec5SDimitry Andric #define DECL(DERIVED, BASE) \
6010b57cec5SDimitry Andric     Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D);
6020b57cec5SDimitry Andric #define ABSTRACT_DECL(DECL)
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric // Decls which never appear inside a class or function.
6050b57cec5SDimitry Andric #define OBJCCONTAINER(DERIVED, BASE)
6060b57cec5SDimitry Andric #define FILESCOPEASM(DERIVED, BASE)
607bdd1243dSDimitry Andric #define TOPLEVELSTMT(DERIVED, BASE)
6080b57cec5SDimitry Andric #define IMPORT(DERIVED, BASE)
6090b57cec5SDimitry Andric #define EXPORT(DERIVED, BASE)
6100b57cec5SDimitry Andric #define LINKAGESPEC(DERIVED, BASE)
6110b57cec5SDimitry Andric #define OBJCCOMPATIBLEALIAS(DERIVED, BASE)
6120b57cec5SDimitry Andric #define OBJCMETHOD(DERIVED, BASE)
6130b57cec5SDimitry Andric #define OBJCTYPEPARAM(DERIVED, BASE)
6140b57cec5SDimitry Andric #define OBJCIVAR(DERIVED, BASE)
6150b57cec5SDimitry Andric #define OBJCPROPERTY(DERIVED, BASE)
6160b57cec5SDimitry Andric #define OBJCPROPERTYIMPL(DERIVED, BASE)
6170b57cec5SDimitry Andric #define EMPTY(DERIVED, BASE)
618480093f4SDimitry Andric #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE)
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric     // Decls which use special-case instantiation code.
6210b57cec5SDimitry Andric #define BLOCK(DERIVED, BASE)
6220b57cec5SDimitry Andric #define CAPTURED(DERIVED, BASE)
6230b57cec5SDimitry Andric #define IMPLICITPARAM(DERIVED, BASE)
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric #include "clang/AST/DeclNodes.inc"
6260b57cec5SDimitry Andric 
627480093f4SDimitry Andric     enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual };
628480093f4SDimitry Andric 
629480093f4SDimitry Andric     void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T,
630480093f4SDimitry Andric                           TypeSourceInfo *&TInfo,
631480093f4SDimitry Andric                           DeclarationNameInfo &NameInfo);
632480093f4SDimitry Andric 
6330b57cec5SDimitry Andric     // A few supplemental visitor functions.
6340b57cec5SDimitry Andric     Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
6350b57cec5SDimitry Andric                              TemplateParameterList *TemplateParams,
636480093f4SDimitry Andric                              RewriteKind RK = RewriteKind::None);
6370b57cec5SDimitry Andric     Decl *VisitFunctionDecl(FunctionDecl *D,
638480093f4SDimitry Andric                             TemplateParameterList *TemplateParams,
639480093f4SDimitry Andric                             RewriteKind RK = RewriteKind::None);
6400b57cec5SDimitry Andric     Decl *VisitDecl(Decl *D);
6410b57cec5SDimitry Andric     Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate,
6420b57cec5SDimitry Andric                        ArrayRef<BindingDecl *> *Bindings = nullptr);
643fe6060f1SDimitry Andric     Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst,
644fe6060f1SDimitry Andric                               LookupResult *Lookup);
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric     // Enable late instantiation of attributes.  Late instantiated attributes
6470b57cec5SDimitry Andric     // will be stored in LA.
enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec * LA)6480b57cec5SDimitry Andric     void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) {
6490b57cec5SDimitry Andric       LateAttrs = LA;
6500b57cec5SDimitry Andric       StartingScope = SemaRef.CurrentInstantiationScope;
6510b57cec5SDimitry Andric     }
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric     // Disable late instantiation of attributes.
disableLateAttributeInstantiation()6540b57cec5SDimitry Andric     void disableLateAttributeInstantiation() {
6550b57cec5SDimitry Andric       LateAttrs = nullptr;
6560b57cec5SDimitry Andric       StartingScope = nullptr;
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric 
getStartingScope()6590b57cec5SDimitry Andric     LocalInstantiationScope *getStartingScope() const { return StartingScope; }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric     using delayed_partial_spec_iterator = SmallVectorImpl<std::pair<
6620b57cec5SDimitry Andric       ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator;
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric     using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair<
6650b57cec5SDimitry Andric         VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator;
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric     /// Return an iterator to the beginning of the set of
6680b57cec5SDimitry Andric     /// "delayed" partial specializations, which must be passed to
6690b57cec5SDimitry Andric     /// InstantiateClassTemplatePartialSpecialization once the class
6700b57cec5SDimitry Andric     /// definition has been completed.
delayed_partial_spec_begin()6710b57cec5SDimitry Andric     delayed_partial_spec_iterator delayed_partial_spec_begin() {
6720b57cec5SDimitry Andric       return OutOfLinePartialSpecs.begin();
6730b57cec5SDimitry Andric     }
6740b57cec5SDimitry Andric 
delayed_var_partial_spec_begin()6750b57cec5SDimitry Andric     delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() {
6760b57cec5SDimitry Andric       return OutOfLineVarPartialSpecs.begin();
6770b57cec5SDimitry Andric     }
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric     /// Return an iterator to the end of the set of
6800b57cec5SDimitry Andric     /// "delayed" partial specializations, which must be passed to
6810b57cec5SDimitry Andric     /// InstantiateClassTemplatePartialSpecialization once the class
6820b57cec5SDimitry Andric     /// definition has been completed.
delayed_partial_spec_end()6830b57cec5SDimitry Andric     delayed_partial_spec_iterator delayed_partial_spec_end() {
6840b57cec5SDimitry Andric       return OutOfLinePartialSpecs.end();
6850b57cec5SDimitry Andric     }
6860b57cec5SDimitry Andric 
delayed_var_partial_spec_end()6870b57cec5SDimitry Andric     delayed_var_partial_spec_iterator delayed_var_partial_spec_end() {
6880b57cec5SDimitry Andric       return OutOfLineVarPartialSpecs.end();
6890b57cec5SDimitry Andric     }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     // Helper functions for instantiating methods.
6920b57cec5SDimitry Andric     TypeSourceInfo *SubstFunctionType(FunctionDecl *D,
6930b57cec5SDimitry Andric                              SmallVectorImpl<ParmVarDecl *> &Params);
6940b57cec5SDimitry Andric     bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl);
6950b57cec5SDimitry Andric     bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl);
6960b57cec5SDimitry Andric 
697480093f4SDimitry Andric     bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl);
698480093f4SDimitry Andric 
6990b57cec5SDimitry Andric     TemplateParameterList *
7000b57cec5SDimitry Andric       SubstTemplateParams(TemplateParameterList *List);
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     bool SubstQualifier(const DeclaratorDecl *OldDecl,
7030b57cec5SDimitry Andric                         DeclaratorDecl *NewDecl);
7040b57cec5SDimitry Andric     bool SubstQualifier(const TagDecl *OldDecl,
7050b57cec5SDimitry Andric                         TagDecl *NewDecl);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric     Decl *VisitVarTemplateSpecializationDecl(
708e8d8bef9SDimitry Andric         VarTemplateDecl *VarTemplate, VarDecl *FromVar,
7090b57cec5SDimitry Andric         const TemplateArgumentListInfo &TemplateArgsInfo,
7100b57cec5SDimitry Andric         ArrayRef<TemplateArgument> Converted,
7110b57cec5SDimitry Andric         VarTemplateSpecializationDecl *PrevDecl = nullptr);
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric     Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias);
7140b57cec5SDimitry Andric     ClassTemplatePartialSpecializationDecl *
7150b57cec5SDimitry Andric     InstantiateClassTemplatePartialSpecialization(
7160b57cec5SDimitry Andric                                               ClassTemplateDecl *ClassTemplate,
7170b57cec5SDimitry Andric                            ClassTemplatePartialSpecializationDecl *PartialSpec);
7180b57cec5SDimitry Andric     VarTemplatePartialSpecializationDecl *
7190b57cec5SDimitry Andric     InstantiateVarTemplatePartialSpecialization(
7200b57cec5SDimitry Andric         VarTemplateDecl *VarTemplate,
7210b57cec5SDimitry Andric         VarTemplatePartialSpecializationDecl *PartialSpec);
7220b57cec5SDimitry Andric     void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern);
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric   private:
7250b57cec5SDimitry Andric     template<typename T>
7260b57cec5SDimitry Andric     Decl *instantiateUnresolvedUsingDecl(T *D,
7270b57cec5SDimitry Andric                                          bool InstantiatingPackElement = false);
7280b57cec5SDimitry Andric   };
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric } // namespace clang
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric #endif // LLVM_CLANG_SEMA_TEMPLATE_H
733