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