xref: /openbsd-src/gnu/llvm/clang/include/clang/Sema/Template.h (revision 12c855180aad702bbcca06e0398d774beeafb155)
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