Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 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(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 | {{AssociatedDecl->getCanonicalDecl(), Final}, Args}); |
||
217 | } |
||
218 | |||
219 | void addOuterTemplateArguments(ArgList Args) { |
||
220 | assert(!NumRetainedOuterLevels && |
||
221 | "substituted args outside retained args?"); |
||
222 | assert(getKind() == TemplateSubstitutionKind::Rewrite); |
||
223 | TemplateArgumentLists.push_back({{}, Args}); |
||
224 | } |
||
225 | |||
226 | void addOuterTemplateArguments(std::nullopt_t) { |
||
227 | assert(!NumRetainedOuterLevels && |
||
228 | "substituted args outside retained args?"); |
||
229 | TemplateArgumentLists.push_back({}); |
||
230 | } |
||
231 | |||
232 | /// Replaces the current 'innermost' level with the provided argument list. |
||
233 | /// This is useful for type deduction cases where we need to get the entire |
||
234 | /// list from the AST, but then add the deduced innermost list. |
||
235 | void replaceInnermostTemplateArguments(ArgList Args) { |
||
236 | assert(TemplateArgumentLists.size() > 0 && "Replacing in an empty list?"); |
||
237 | TemplateArgumentLists[0].Args = Args; |
||
238 | } |
||
239 | |||
240 | /// Add an outermost level that we are not substituting. We have no |
||
241 | /// arguments at this level, and do not remove it from the depth of inner |
||
242 | /// template parameters that we instantiate. |
||
243 | void addOuterRetainedLevel() { |
||
244 | ++NumRetainedOuterLevels; |
||
245 | } |
||
246 | void addOuterRetainedLevels(unsigned Num) { |
||
247 | NumRetainedOuterLevels += Num; |
||
248 | } |
||
249 | |||
250 | /// Retrieve the innermost template argument list. |
||
251 | const ArgList &getInnermost() const { |
||
252 | return TemplateArgumentLists.front().Args; |
||
253 | } |
||
254 | /// Retrieve the outermost template argument list. |
||
255 | const ArgList &getOutermost() const { |
||
256 | return TemplateArgumentLists.back().Args; |
||
257 | } |
||
258 | ArgListsIterator begin() { return TemplateArgumentLists.begin(); } |
||
259 | ConstArgListsIterator begin() const { |
||
260 | return TemplateArgumentLists.begin(); |
||
261 | } |
||
262 | ArgListsIterator end() { return TemplateArgumentLists.end(); } |
||
263 | ConstArgListsIterator end() const { return TemplateArgumentLists.end(); } |
||
264 | }; |
||
265 | |||
266 | /// The context in which partial ordering of function templates occurs. |
||
267 | enum TPOC { |
||
268 | /// Partial ordering of function templates for a function call. |
||
269 | TPOC_Call, |
||
270 | |||
271 | /// Partial ordering of function templates for a call to a |
||
272 | /// conversion function. |
||
273 | TPOC_Conversion, |
||
274 | |||
275 | /// Partial ordering of function templates in other contexts, e.g., |
||
276 | /// taking the address of a function template or matching a function |
||
277 | /// template specialization to a function template. |
||
278 | TPOC_Other |
||
279 | }; |
||
280 | |||
281 | // This is lame but unavoidable in a world without forward |
||
282 | // declarations of enums. The alternatives are to either pollute |
||
283 | // Sema.h (by including this file) or sacrifice type safety (by |
||
284 | // making Sema.h declare things as enums). |
||
285 | class TemplatePartialOrderingContext { |
||
286 | TPOC Value; |
||
287 | |||
288 | public: |
||
289 | TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} |
||
290 | |||
291 | operator TPOC() const { return Value; } |
||
292 | }; |
||
293 | |||
294 | /// Captures a template argument whose value has been deduced |
||
295 | /// via c++ template argument deduction. |
||
296 | class DeducedTemplateArgument : public TemplateArgument { |
||
297 | /// For a non-type template argument, whether the value was |
||
298 | /// deduced from an array bound. |
||
299 | bool DeducedFromArrayBound = false; |
||
300 | |||
301 | public: |
||
302 | DeducedTemplateArgument() = default; |
||
303 | |||
304 | DeducedTemplateArgument(const TemplateArgument &Arg, |
||
305 | bool DeducedFromArrayBound = false) |
||
306 | : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {} |
||
307 | |||
308 | /// Construct an integral non-type template argument that |
||
309 | /// has been deduced, possibly from an array bound. |
||
310 | DeducedTemplateArgument(ASTContext &Ctx, |
||
311 | const llvm::APSInt &Value, |
||
312 | QualType ValueType, |
||
313 | bool DeducedFromArrayBound) |
||
314 | : TemplateArgument(Ctx, Value, ValueType), |
||
315 | DeducedFromArrayBound(DeducedFromArrayBound) {} |
||
316 | |||
317 | /// For a non-type template argument, determine whether the |
||
318 | /// template argument was deduced from an array bound. |
||
319 | bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } |
||
320 | |||
321 | /// Specify whether the given non-type template argument |
||
322 | /// was deduced from an array bound. |
||
323 | void setDeducedFromArrayBound(bool Deduced) { |
||
324 | DeducedFromArrayBound = Deduced; |
||
325 | } |
||
326 | }; |
||
327 | |||
328 | /// A stack-allocated class that identifies which local |
||
329 | /// variable declaration instantiations are present in this scope. |
||
330 | /// |
||
331 | /// A new instance of this class type will be created whenever we |
||
332 | /// instantiate a new function declaration, which will have its own |
||
333 | /// set of parameter declarations. |
||
334 | class LocalInstantiationScope { |
||
335 | public: |
||
336 | /// A set of declarations. |
||
337 | using DeclArgumentPack = SmallVector<VarDecl *, 4>; |
||
338 | |||
339 | private: |
||
340 | /// Reference to the semantic analysis that is performing |
||
341 | /// this template instantiation. |
||
342 | Sema &SemaRef; |
||
343 | |||
344 | using LocalDeclsMap = |
||
345 | llvm::SmallDenseMap<const Decl *, |
||
346 | llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>; |
||
347 | |||
348 | /// A mapping from local declarations that occur |
||
349 | /// within a template to their instantiations. |
||
350 | /// |
||
351 | /// This mapping is used during instantiation to keep track of, |
||
352 | /// e.g., function parameter and variable declarations. For example, |
||
353 | /// given: |
||
354 | /// |
||
355 | /// \code |
||
356 | /// template<typename T> T add(T x, T y) { return x + y; } |
||
357 | /// \endcode |
||
358 | /// |
||
359 | /// when we instantiate add<int>, we will introduce a mapping from |
||
360 | /// the ParmVarDecl for 'x' that occurs in the template to the |
||
361 | /// instantiated ParmVarDecl for 'x'. |
||
362 | /// |
||
363 | /// For a parameter pack, the local instantiation scope may contain a |
||
364 | /// set of instantiated parameters. This is stored as a DeclArgumentPack |
||
365 | /// pointer. |
||
366 | LocalDeclsMap LocalDecls; |
||
367 | |||
368 | /// The set of argument packs we've allocated. |
||
369 | SmallVector<DeclArgumentPack *, 1> ArgumentPacks; |
||
370 | |||
371 | /// The outer scope, which contains local variable |
||
372 | /// definitions from some other instantiation (that may not be |
||
373 | /// relevant to this particular scope). |
||
374 | LocalInstantiationScope *Outer; |
||
375 | |||
376 | /// Whether we have already exited this scope. |
||
377 | bool Exited = false; |
||
378 | |||
379 | /// Whether to combine this scope with the outer scope, such that |
||
380 | /// lookup will search our outer scope. |
||
381 | bool CombineWithOuterScope; |
||
382 | |||
383 | /// If non-NULL, the template parameter pack that has been |
||
384 | /// partially substituted per C++0x [temp.arg.explicit]p9. |
||
385 | NamedDecl *PartiallySubstitutedPack = nullptr; |
||
386 | |||
387 | /// If \c PartiallySubstitutedPack is non-null, the set of |
||
388 | /// explicitly-specified template arguments in that pack. |
||
389 | const TemplateArgument *ArgsInPartiallySubstitutedPack; |
||
390 | |||
391 | /// If \c PartiallySubstitutedPack, the number of |
||
392 | /// explicitly-specified template arguments in |
||
393 | /// ArgsInPartiallySubstitutedPack. |
||
394 | unsigned NumArgsInPartiallySubstitutedPack; |
||
395 | |||
396 | public: |
||
397 | LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) |
||
398 | : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), |
||
399 | CombineWithOuterScope(CombineWithOuterScope) { |
||
400 | SemaRef.CurrentInstantiationScope = this; |
||
401 | } |
||
402 | |||
403 | LocalInstantiationScope(const LocalInstantiationScope &) = delete; |
||
404 | LocalInstantiationScope & |
||
405 | operator=(const LocalInstantiationScope &) = delete; |
||
406 | |||
407 | ~LocalInstantiationScope() { |
||
408 | Exit(); |
||
409 | } |
||
410 | |||
411 | const Sema &getSema() const { return SemaRef; } |
||
412 | |||
413 | /// Exit this local instantiation scope early. |
||
414 | void Exit() { |
||
415 | if (Exited) |
||
416 | return; |
||
417 | |||
418 | for (unsigned I = 0, N = ArgumentPacks.size(); I != N; ++I) |
||
419 | delete ArgumentPacks[I]; |
||
420 | |||
421 | SemaRef.CurrentInstantiationScope = Outer; |
||
422 | Exited = true; |
||
423 | } |
||
424 | |||
425 | /// Clone this scope, and all outer scopes, down to the given |
||
426 | /// outermost scope. |
||
427 | LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { |
||
428 | if (this == Outermost) return this; |
||
429 | |||
430 | // Save the current scope from SemaRef since the LocalInstantiationScope |
||
431 | // will overwrite it on construction |
||
432 | LocalInstantiationScope *oldScope = SemaRef.CurrentInstantiationScope; |
||
433 | |||
434 | LocalInstantiationScope *newScope = |
||
435 | new LocalInstantiationScope(SemaRef, CombineWithOuterScope); |
||
436 | |||
437 | newScope->Outer = nullptr; |
||
438 | if (Outer) |
||
439 | newScope->Outer = Outer->cloneScopes(Outermost); |
||
440 | |||
441 | newScope->PartiallySubstitutedPack = PartiallySubstitutedPack; |
||
442 | newScope->ArgsInPartiallySubstitutedPack = ArgsInPartiallySubstitutedPack; |
||
443 | newScope->NumArgsInPartiallySubstitutedPack = |
||
444 | NumArgsInPartiallySubstitutedPack; |
||
445 | |||
446 | for (LocalDeclsMap::iterator I = LocalDecls.begin(), E = LocalDecls.end(); |
||
447 | I != E; ++I) { |
||
448 | const Decl *D = I->first; |
||
449 | llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = |
||
450 | newScope->LocalDecls[D]; |
||
451 | if (I->second.is<Decl *>()) { |
||
452 | Stored = I->second.get<Decl *>(); |
||
453 | } else { |
||
454 | DeclArgumentPack *OldPack = I->second.get<DeclArgumentPack *>(); |
||
455 | DeclArgumentPack *NewPack = new DeclArgumentPack(*OldPack); |
||
456 | Stored = NewPack; |
||
457 | newScope->ArgumentPacks.push_back(NewPack); |
||
458 | } |
||
459 | } |
||
460 | // Restore the saved scope to SemaRef |
||
461 | SemaRef.CurrentInstantiationScope = oldScope; |
||
462 | return newScope; |
||
463 | } |
||
464 | |||
465 | /// deletes the given scope, and all outer scopes, down to the |
||
466 | /// given outermost scope. |
||
467 | static void deleteScopes(LocalInstantiationScope *Scope, |
||
468 | LocalInstantiationScope *Outermost) { |
||
469 | while (Scope && Scope != Outermost) { |
||
470 | LocalInstantiationScope *Out = Scope->Outer; |
||
471 | delete Scope; |
||
472 | Scope = Out; |
||
473 | } |
||
474 | } |
||
475 | |||
476 | /// Find the instantiation of the declaration D within the current |
||
477 | /// instantiation scope. |
||
478 | /// |
||
479 | /// \param D The declaration whose instantiation we are searching for. |
||
480 | /// |
||
481 | /// \returns A pointer to the declaration or argument pack of declarations |
||
482 | /// to which the declaration \c D is instantiated, if found. Otherwise, |
||
483 | /// returns NULL. |
||
484 | llvm::PointerUnion<Decl *, DeclArgumentPack *> * |
||
485 | findInstantiationOf(const Decl *D); |
||
486 | |||
487 | void InstantiatedLocal(const Decl *D, Decl *Inst); |
||
488 | void InstantiatedLocalPackArg(const Decl *D, VarDecl *Inst); |
||
489 | void MakeInstantiatedLocalArgPack(const Decl *D); |
||
490 | |||
491 | /// Note that the given parameter pack has been partially substituted |
||
492 | /// via explicit specification of template arguments |
||
493 | /// (C++0x [temp.arg.explicit]p9). |
||
494 | /// |
||
495 | /// \param Pack The parameter pack, which will always be a template |
||
496 | /// parameter pack. |
||
497 | /// |
||
498 | /// \param ExplicitArgs The explicitly-specified template arguments provided |
||
499 | /// for this parameter pack. |
||
500 | /// |
||
501 | /// \param NumExplicitArgs The number of explicitly-specified template |
||
502 | /// arguments provided for this parameter pack. |
||
503 | void SetPartiallySubstitutedPack(NamedDecl *Pack, |
||
504 | const TemplateArgument *ExplicitArgs, |
||
505 | unsigned NumExplicitArgs); |
||
506 | |||
507 | /// Reset the partially-substituted pack when it is no longer of |
||
508 | /// interest. |
||
509 | void ResetPartiallySubstitutedPack() { |
||
510 | assert(PartiallySubstitutedPack && "No partially-substituted pack"); |
||
511 | PartiallySubstitutedPack = nullptr; |
||
512 | ArgsInPartiallySubstitutedPack = nullptr; |
||
513 | NumArgsInPartiallySubstitutedPack = 0; |
||
514 | } |
||
515 | |||
516 | /// Retrieve the partially-substitued template parameter pack. |
||
517 | /// |
||
518 | /// If there is no partially-substituted parameter pack, returns NULL. |
||
519 | NamedDecl * |
||
520 | getPartiallySubstitutedPack(const TemplateArgument **ExplicitArgs = nullptr, |
||
521 | unsigned *NumExplicitArgs = nullptr) const; |
||
522 | |||
523 | /// Determine whether D is a pack expansion created in this scope. |
||
524 | bool isLocalPackExpansion(const Decl *D); |
||
525 | }; |
||
526 | |||
527 | class TemplateDeclInstantiator |
||
528 | : public DeclVisitor<TemplateDeclInstantiator, Decl *> |
||
529 | { |
||
530 | Sema &SemaRef; |
||
531 | Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; |
||
532 | DeclContext *Owner; |
||
533 | const MultiLevelTemplateArgumentList &TemplateArgs; |
||
534 | Sema::LateInstantiatedAttrVec* LateAttrs = nullptr; |
||
535 | LocalInstantiationScope *StartingScope = nullptr; |
||
536 | bool EvaluateConstraints = true; |
||
537 | |||
538 | /// A list of out-of-line class template partial |
||
539 | /// specializations that will need to be instantiated after the |
||
540 | /// enclosing class's instantiation is complete. |
||
541 | SmallVector<std::pair<ClassTemplateDecl *, |
||
542 | ClassTemplatePartialSpecializationDecl *>, 4> |
||
543 | OutOfLinePartialSpecs; |
||
544 | |||
545 | /// A list of out-of-line variable template partial |
||
546 | /// specializations that will need to be instantiated after the |
||
547 | /// enclosing variable's instantiation is complete. |
||
548 | /// FIXME: Verify that this is needed. |
||
549 | SmallVector< |
||
550 | std::pair<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>, 4> |
||
551 | OutOfLineVarPartialSpecs; |
||
552 | |||
553 | public: |
||
554 | TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, |
||
555 | const MultiLevelTemplateArgumentList &TemplateArgs) |
||
556 | : SemaRef(SemaRef), |
||
557 | SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), |
||
558 | Owner(Owner), TemplateArgs(TemplateArgs) {} |
||
559 | |||
560 | void setEvaluateConstraints(bool B) { |
||
561 | EvaluateConstraints = B; |
||
562 | } |
||
563 | bool getEvaluateConstraints() { |
||
564 | return EvaluateConstraints; |
||
565 | } |
||
566 | |||
567 | // Define all the decl visitors using DeclNodes.inc |
||
568 | #define DECL(DERIVED, BASE) \ |
||
569 | Decl *Visit ## DERIVED ## Decl(DERIVED ## Decl *D); |
||
570 | #define ABSTRACT_DECL(DECL) |
||
571 | |||
572 | // Decls which never appear inside a class or function. |
||
573 | #define OBJCCONTAINER(DERIVED, BASE) |
||
574 | #define FILESCOPEASM(DERIVED, BASE) |
||
575 | #define TOPLEVELSTMT(DERIVED, BASE) |
||
576 | #define IMPORT(DERIVED, BASE) |
||
577 | #define EXPORT(DERIVED, BASE) |
||
578 | #define LINKAGESPEC(DERIVED, BASE) |
||
579 | #define OBJCCOMPATIBLEALIAS(DERIVED, BASE) |
||
580 | #define OBJCMETHOD(DERIVED, BASE) |
||
581 | #define OBJCTYPEPARAM(DERIVED, BASE) |
||
582 | #define OBJCIVAR(DERIVED, BASE) |
||
583 | #define OBJCPROPERTY(DERIVED, BASE) |
||
584 | #define OBJCPROPERTYIMPL(DERIVED, BASE) |
||
585 | #define EMPTY(DERIVED, BASE) |
||
586 | #define LIFETIMEEXTENDEDTEMPORARY(DERIVED, BASE) |
||
587 | |||
588 | // Decls which use special-case instantiation code. |
||
589 | #define BLOCK(DERIVED, BASE) |
||
590 | #define CAPTURED(DERIVED, BASE) |
||
591 | #define IMPLICITPARAM(DERIVED, BASE) |
||
592 | |||
593 | #include "clang/AST/DeclNodes.inc" |
||
594 | |||
595 | enum class RewriteKind { None, RewriteSpaceshipAsEqualEqual }; |
||
596 | |||
597 | void adjustForRewrite(RewriteKind RK, FunctionDecl *Orig, QualType &T, |
||
598 | TypeSourceInfo *&TInfo, |
||
599 | DeclarationNameInfo &NameInfo); |
||
600 | |||
601 | // A few supplemental visitor functions. |
||
602 | Decl *VisitCXXMethodDecl(CXXMethodDecl *D, |
||
603 | TemplateParameterList *TemplateParams, |
||
604 | std::optional<const ASTTemplateArgumentListInfo *> |
||
605 | ClassScopeSpecializationArgs = std::nullopt, |
||
606 | RewriteKind RK = RewriteKind::None); |
||
607 | Decl *VisitFunctionDecl(FunctionDecl *D, |
||
608 | TemplateParameterList *TemplateParams, |
||
609 | RewriteKind RK = RewriteKind::None); |
||
610 | Decl *VisitDecl(Decl *D); |
||
611 | Decl *VisitVarDecl(VarDecl *D, bool InstantiatingVarTemplate, |
||
612 | ArrayRef<BindingDecl *> *Bindings = nullptr); |
||
613 | Decl *VisitBaseUsingDecls(BaseUsingDecl *D, BaseUsingDecl *Inst, |
||
614 | LookupResult *Lookup); |
||
615 | |||
616 | // Enable late instantiation of attributes. Late instantiated attributes |
||
617 | // will be stored in LA. |
||
618 | void enableLateAttributeInstantiation(Sema::LateInstantiatedAttrVec *LA) { |
||
619 | LateAttrs = LA; |
||
620 | StartingScope = SemaRef.CurrentInstantiationScope; |
||
621 | } |
||
622 | |||
623 | // Disable late instantiation of attributes. |
||
624 | void disableLateAttributeInstantiation() { |
||
625 | LateAttrs = nullptr; |
||
626 | StartingScope = nullptr; |
||
627 | } |
||
628 | |||
629 | LocalInstantiationScope *getStartingScope() const { return StartingScope; } |
||
630 | |||
631 | using delayed_partial_spec_iterator = SmallVectorImpl<std::pair< |
||
632 | ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator; |
||
633 | |||
634 | using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair< |
||
635 | VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator; |
||
636 | |||
637 | /// Return an iterator to the beginning of the set of |
||
638 | /// "delayed" partial specializations, which must be passed to |
||
639 | /// InstantiateClassTemplatePartialSpecialization once the class |
||
640 | /// definition has been completed. |
||
641 | delayed_partial_spec_iterator delayed_partial_spec_begin() { |
||
642 | return OutOfLinePartialSpecs.begin(); |
||
643 | } |
||
644 | |||
645 | delayed_var_partial_spec_iterator delayed_var_partial_spec_begin() { |
||
646 | return OutOfLineVarPartialSpecs.begin(); |
||
647 | } |
||
648 | |||
649 | /// Return an iterator to the end of the set of |
||
650 | /// "delayed" partial specializations, which must be passed to |
||
651 | /// InstantiateClassTemplatePartialSpecialization once the class |
||
652 | /// definition has been completed. |
||
653 | delayed_partial_spec_iterator delayed_partial_spec_end() { |
||
654 | return OutOfLinePartialSpecs.end(); |
||
655 | } |
||
656 | |||
657 | delayed_var_partial_spec_iterator delayed_var_partial_spec_end() { |
||
658 | return OutOfLineVarPartialSpecs.end(); |
||
659 | } |
||
660 | |||
661 | // Helper functions for instantiating methods. |
||
662 | TypeSourceInfo *SubstFunctionType(FunctionDecl *D, |
||
663 | SmallVectorImpl<ParmVarDecl *> &Params); |
||
664 | bool InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl); |
||
665 | bool InitMethodInstantiation(CXXMethodDecl *New, CXXMethodDecl *Tmpl); |
||
666 | |||
667 | bool SubstDefaultedFunction(FunctionDecl *New, FunctionDecl *Tmpl); |
||
668 | |||
669 | TemplateParameterList * |
||
670 | SubstTemplateParams(TemplateParameterList *List); |
||
671 | |||
672 | bool SubstQualifier(const DeclaratorDecl *OldDecl, |
||
673 | DeclaratorDecl *NewDecl); |
||
674 | bool SubstQualifier(const TagDecl *OldDecl, |
||
675 | TagDecl *NewDecl); |
||
676 | |||
677 | Decl *VisitVarTemplateSpecializationDecl( |
||
678 | VarTemplateDecl *VarTemplate, VarDecl *FromVar, |
||
679 | const TemplateArgumentListInfo &TemplateArgsInfo, |
||
680 | ArrayRef<TemplateArgument> Converted, |
||
681 | VarTemplateSpecializationDecl *PrevDecl = nullptr); |
||
682 | |||
683 | Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); |
||
684 | ClassTemplatePartialSpecializationDecl * |
||
685 | InstantiateClassTemplatePartialSpecialization( |
||
686 | ClassTemplateDecl *ClassTemplate, |
||
687 | ClassTemplatePartialSpecializationDecl *PartialSpec); |
||
688 | VarTemplatePartialSpecializationDecl * |
||
689 | InstantiateVarTemplatePartialSpecialization( |
||
690 | VarTemplateDecl *VarTemplate, |
||
691 | VarTemplatePartialSpecializationDecl *PartialSpec); |
||
692 | void InstantiateEnumDefinition(EnumDecl *Enum, EnumDecl *Pattern); |
||
693 | |||
694 | private: |
||
695 | template<typename T> |
||
696 | Decl *instantiateUnresolvedUsingDecl(T *D, |
||
697 | bool InstantiatingPackElement = false); |
||
698 | }; |
||
699 | |||
700 | } // namespace clang |
||
701 | |||
702 | #endif // LLVM_CLANG_SEMA_TEMPLATE_H |