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