Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- TemplateDeduction.h - C++ template argument deduction ----*- 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 | // |
||
9 | // This file provides types used with Sema's template argument deduction |
||
10 | // routines. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H |
||
15 | #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H |
||
16 | |||
17 | #include "clang/Sema/Ownership.h" |
||
18 | #include "clang/Sema/SemaConcept.h" |
||
19 | #include "clang/AST/ASTConcept.h" |
||
20 | #include "clang/AST/DeclAccessPair.h" |
||
21 | #include "clang/AST/DeclTemplate.h" |
||
22 | #include "clang/AST/TemplateBase.h" |
||
23 | #include "clang/Basic/PartialDiagnostic.h" |
||
24 | #include "clang/Basic/SourceLocation.h" |
||
25 | #include "llvm/ADT/SmallVector.h" |
||
26 | #include <cassert> |
||
27 | #include <cstddef> |
||
28 | #include <optional> |
||
29 | #include <utility> |
||
30 | |||
31 | namespace clang { |
||
32 | |||
33 | class Decl; |
||
34 | struct DeducedPack; |
||
35 | class Sema; |
||
36 | |||
37 | namespace sema { |
||
38 | |||
39 | /// Provides information about an attempted template argument |
||
40 | /// deduction, whose success or failure was described by a |
||
41 | /// TemplateDeductionResult value. |
||
42 | class TemplateDeductionInfo { |
||
43 | /// The deduced template argument list. |
||
44 | TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr; |
||
45 | |||
46 | /// The source location at which template argument |
||
47 | /// deduction is occurring. |
||
48 | SourceLocation Loc; |
||
49 | |||
50 | /// Have we suppressed an error during deduction? |
||
51 | bool HasSFINAEDiagnostic = false; |
||
52 | |||
53 | /// The template parameter depth for which we're performing deduction. |
||
54 | unsigned DeducedDepth; |
||
55 | |||
56 | /// The number of parameters with explicitly-specified template arguments, |
||
57 | /// up to and including the partially-specified pack (if any). |
||
58 | unsigned ExplicitArgs = 0; |
||
59 | |||
60 | /// Warnings (and follow-on notes) that were suppressed due to |
||
61 | /// SFINAE while performing template argument deduction. |
||
62 | SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; |
||
63 | |||
64 | public: |
||
65 | TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0) |
||
66 | : Loc(Loc), DeducedDepth(DeducedDepth) {} |
||
67 | TemplateDeductionInfo(const TemplateDeductionInfo &) = delete; |
||
68 | TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete; |
||
69 | |||
70 | enum ForBaseTag { ForBase }; |
||
71 | /// Create temporary template deduction info for speculatively deducing |
||
72 | /// against a base class of an argument's type. |
||
73 | TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info) |
||
74 | : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc), |
||
75 | DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {} |
||
76 | |||
77 | /// Returns the location at which template argument is |
||
78 | /// occurring. |
||
79 | SourceLocation getLocation() const { |
||
80 | return Loc; |
||
81 | } |
||
82 | |||
83 | /// The depth of template parameters for which deduction is being |
||
84 | /// performed. |
||
85 | unsigned getDeducedDepth() const { |
||
86 | return DeducedDepth; |
||
87 | } |
||
88 | |||
89 | /// Get the number of explicitly-specified arguments. |
||
90 | unsigned getNumExplicitArgs() const { |
||
91 | return ExplicitArgs; |
||
92 | } |
||
93 | |||
94 | /// Take ownership of the deduced template argument lists. |
||
95 | TemplateArgumentList *takeSugared() { |
||
96 | TemplateArgumentList *Result = DeducedSugared; |
||
97 | DeducedSugared = nullptr; |
||
98 | return Result; |
||
99 | } |
||
100 | TemplateArgumentList *takeCanonical() { |
||
101 | TemplateArgumentList *Result = DeducedCanonical; |
||
102 | DeducedCanonical = nullptr; |
||
103 | return Result; |
||
104 | } |
||
105 | |||
106 | /// Take ownership of the SFINAE diagnostic. |
||
107 | void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) { |
||
108 | assert(HasSFINAEDiagnostic); |
||
109 | PD.first = SuppressedDiagnostics.front().first; |
||
110 | PD.second.swap(SuppressedDiagnostics.front().second); |
||
111 | clearSFINAEDiagnostic(); |
||
112 | } |
||
113 | |||
114 | /// Discard any SFINAE diagnostics. |
||
115 | void clearSFINAEDiagnostic() { |
||
116 | SuppressedDiagnostics.clear(); |
||
117 | HasSFINAEDiagnostic = false; |
||
118 | } |
||
119 | |||
120 | /// Peek at the SFINAE diagnostic. |
||
121 | const PartialDiagnosticAt &peekSFINAEDiagnostic() const { |
||
122 | assert(HasSFINAEDiagnostic); |
||
123 | return SuppressedDiagnostics.front(); |
||
124 | } |
||
125 | |||
126 | /// Provide an initial template argument list that contains the |
||
127 | /// explicitly-specified arguments. |
||
128 | void setExplicitArgs(TemplateArgumentList *NewDeducedSugared, |
||
129 | TemplateArgumentList *NewDeducedCanonical) { |
||
130 | assert(NewDeducedSugared->size() == NewDeducedCanonical->size()); |
||
131 | DeducedSugared = NewDeducedSugared; |
||
132 | DeducedCanonical = NewDeducedCanonical; |
||
133 | ExplicitArgs = DeducedSugared->size(); |
||
134 | } |
||
135 | |||
136 | /// Provide a new template argument list that contains the |
||
137 | /// results of template argument deduction. |
||
138 | void reset(TemplateArgumentList *NewDeducedSugared, |
||
139 | TemplateArgumentList *NewDeducedCanonical) { |
||
140 | DeducedSugared = NewDeducedSugared; |
||
141 | DeducedCanonical = NewDeducedCanonical; |
||
142 | } |
||
143 | |||
144 | /// Is a SFINAE diagnostic available? |
||
145 | bool hasSFINAEDiagnostic() const { |
||
146 | return HasSFINAEDiagnostic; |
||
147 | } |
||
148 | |||
149 | /// Set the diagnostic which caused the SFINAE failure. |
||
150 | void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { |
||
151 | // Only collect the first diagnostic. |
||
152 | if (HasSFINAEDiagnostic) |
||
153 | return; |
||
154 | SuppressedDiagnostics.clear(); |
||
155 | SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); |
||
156 | HasSFINAEDiagnostic = true; |
||
157 | } |
||
158 | |||
159 | /// Add a new diagnostic to the set of diagnostics |
||
160 | void addSuppressedDiagnostic(SourceLocation Loc, |
||
161 | PartialDiagnostic PD) { |
||
162 | if (HasSFINAEDiagnostic) |
||
163 | return; |
||
164 | SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); |
||
165 | } |
||
166 | |||
167 | /// Iterator over the set of suppressed diagnostics. |
||
168 | using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator; |
||
169 | |||
170 | /// Returns an iterator at the beginning of the sequence of suppressed |
||
171 | /// diagnostics. |
||
172 | diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); } |
||
173 | |||
174 | /// Returns an iterator at the end of the sequence of suppressed |
||
175 | /// diagnostics. |
||
176 | diag_iterator diag_end() const { return SuppressedDiagnostics.end(); } |
||
177 | |||
178 | /// The template parameter to which a template argument |
||
179 | /// deduction failure refers. |
||
180 | /// |
||
181 | /// Depending on the result of template argument deduction, this |
||
182 | /// template parameter may have different meanings: |
||
183 | /// |
||
184 | /// TDK_Incomplete: this is the first template parameter whose |
||
185 | /// corresponding template argument was not deduced. |
||
186 | /// |
||
187 | /// TDK_IncompletePack: this is the expanded parameter pack for |
||
188 | /// which we deduced too few arguments. |
||
189 | /// |
||
190 | /// TDK_Inconsistent: this is the template parameter for which |
||
191 | /// two different template argument values were deduced. |
||
192 | TemplateParameter Param; |
||
193 | |||
194 | /// The first template argument to which the template |
||
195 | /// argument deduction failure refers. |
||
196 | /// |
||
197 | /// Depending on the result of the template argument deduction, |
||
198 | /// this template argument may have different meanings: |
||
199 | /// |
||
200 | /// TDK_IncompletePack: this is the number of arguments we deduced |
||
201 | /// for the pack. |
||
202 | /// |
||
203 | /// TDK_Inconsistent: this argument is the first value deduced |
||
204 | /// for the corresponding template parameter. |
||
205 | /// |
||
206 | /// TDK_SubstitutionFailure: this argument is the template |
||
207 | /// argument we were instantiating when we encountered an error. |
||
208 | /// |
||
209 | /// TDK_DeducedMismatch: this is the parameter type, after substituting |
||
210 | /// deduced arguments. |
||
211 | /// |
||
212 | /// TDK_NonDeducedMismatch: this is the component of the 'parameter' |
||
213 | /// of the deduction, directly provided in the source code. |
||
214 | TemplateArgument FirstArg; |
||
215 | |||
216 | /// The second template argument to which the template |
||
217 | /// argument deduction failure refers. |
||
218 | /// |
||
219 | /// TDK_Inconsistent: this argument is the second value deduced |
||
220 | /// for the corresponding template parameter. |
||
221 | /// |
||
222 | /// TDK_DeducedMismatch: this is the (adjusted) call argument type. |
||
223 | /// |
||
224 | /// TDK_NonDeducedMismatch: this is the mismatching component of the |
||
225 | /// 'argument' of the deduction, from which we are deducing arguments. |
||
226 | /// |
||
227 | /// FIXME: Finish documenting this. |
||
228 | TemplateArgument SecondArg; |
||
229 | |||
230 | /// The index of the function argument that caused a deduction |
||
231 | /// failure. |
||
232 | /// |
||
233 | /// TDK_DeducedMismatch: this is the index of the argument that had a |
||
234 | /// different argument type from its substituted parameter type. |
||
235 | unsigned CallArgIndex = 0; |
||
236 | |||
237 | /// Information on packs that we're currently expanding. |
||
238 | /// |
||
239 | /// FIXME: This should be kept internal to SemaTemplateDeduction. |
||
240 | SmallVector<DeducedPack *, 8> PendingDeducedPacks; |
||
241 | |||
242 | /// \brief The constraint satisfaction details resulting from the associated |
||
243 | /// constraints satisfaction tests. |
||
244 | ConstraintSatisfaction AssociatedConstraintsSatisfaction; |
||
245 | }; |
||
246 | |||
247 | } // namespace sema |
||
248 | |||
249 | /// A structure used to record information about a failed |
||
250 | /// template argument deduction, for diagnosis. |
||
251 | struct DeductionFailureInfo { |
||
252 | /// A Sema::TemplateDeductionResult. |
||
253 | unsigned Result : 8; |
||
254 | |||
255 | /// Indicates whether a diagnostic is stored in Diagnostic. |
||
256 | unsigned HasDiagnostic : 1; |
||
257 | |||
258 | /// Opaque pointer containing additional data about |
||
259 | /// this deduction failure. |
||
260 | void *Data; |
||
261 | |||
262 | /// A diagnostic indicating why deduction failed. |
||
263 | alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)]; |
||
264 | |||
265 | /// Retrieve the diagnostic which caused this deduction failure, |
||
266 | /// if any. |
||
267 | PartialDiagnosticAt *getSFINAEDiagnostic(); |
||
268 | |||
269 | /// Retrieve the template parameter this deduction failure |
||
270 | /// refers to, if any. |
||
271 | TemplateParameter getTemplateParameter(); |
||
272 | |||
273 | /// Retrieve the template argument list associated with this |
||
274 | /// deduction failure, if any. |
||
275 | TemplateArgumentList *getTemplateArgumentList(); |
||
276 | |||
277 | /// Return the first template argument this deduction failure |
||
278 | /// refers to, if any. |
||
279 | const TemplateArgument *getFirstArg(); |
||
280 | |||
281 | /// Return the second template argument this deduction failure |
||
282 | /// refers to, if any. |
||
283 | const TemplateArgument *getSecondArg(); |
||
284 | |||
285 | /// Return the index of the call argument that this deduction |
||
286 | /// failure refers to, if any. |
||
287 | std::optional<unsigned> getCallArgIndex(); |
||
288 | |||
289 | /// Free any memory associated with this deduction failure. |
||
290 | void Destroy(); |
||
291 | }; |
||
292 | |||
293 | /// TemplateSpecCandidate - This is a generalization of OverloadCandidate |
||
294 | /// which keeps track of template argument deduction failure info, when |
||
295 | /// handling explicit specializations (and instantiations) of templates |
||
296 | /// beyond function overloading. |
||
297 | /// For now, assume that the candidates are non-matching specializations. |
||
298 | /// TODO: In the future, we may need to unify/generalize this with |
||
299 | /// OverloadCandidate. |
||
300 | struct TemplateSpecCandidate { |
||
301 | /// The declaration that was looked up, together with its access. |
||
302 | /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl. |
||
303 | DeclAccessPair FoundDecl; |
||
304 | |||
305 | /// Specialization - The actual specialization that this candidate |
||
306 | /// represents. When NULL, this may be a built-in candidate. |
||
307 | Decl *Specialization; |
||
308 | |||
309 | /// Template argument deduction info |
||
310 | DeductionFailureInfo DeductionFailure; |
||
311 | |||
312 | void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) { |
||
313 | FoundDecl = Found; |
||
314 | Specialization = Spec; |
||
315 | DeductionFailure = Info; |
||
316 | } |
||
317 | |||
318 | /// Diagnose a template argument deduction failure. |
||
319 | void NoteDeductionFailure(Sema &S, bool ForTakingAddress); |
||
320 | }; |
||
321 | |||
322 | /// TemplateSpecCandidateSet - A set of generalized overload candidates, |
||
323 | /// used in template specializations. |
||
324 | /// TODO: In the future, we may need to unify/generalize this with |
||
325 | /// OverloadCandidateSet. |
||
326 | class TemplateSpecCandidateSet { |
||
327 | SmallVector<TemplateSpecCandidate, 16> Candidates; |
||
328 | SourceLocation Loc; |
||
329 | |||
330 | // Stores whether we're taking the address of these candidates. This helps us |
||
331 | // produce better error messages when dealing with the pass_object_size |
||
332 | // attribute on parameters. |
||
333 | bool ForTakingAddress; |
||
334 | |||
335 | void destroyCandidates(); |
||
336 | |||
337 | public: |
||
338 | TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false) |
||
339 | : Loc(Loc), ForTakingAddress(ForTakingAddress) {} |
||
340 | TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete; |
||
341 | TemplateSpecCandidateSet & |
||
342 | operator=(const TemplateSpecCandidateSet &) = delete; |
||
343 | ~TemplateSpecCandidateSet() { destroyCandidates(); } |
||
344 | |||
345 | SourceLocation getLocation() const { return Loc; } |
||
346 | |||
347 | /// Clear out all of the candidates. |
||
348 | /// TODO: This may be unnecessary. |
||
349 | void clear(); |
||
350 | |||
351 | using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator; |
||
352 | |||
353 | iterator begin() { return Candidates.begin(); } |
||
354 | iterator end() { return Candidates.end(); } |
||
355 | |||
356 | size_t size() const { return Candidates.size(); } |
||
357 | bool empty() const { return Candidates.empty(); } |
||
358 | |||
359 | /// Add a new candidate with NumConversions conversion sequence slots |
||
360 | /// to the overload set. |
||
361 | TemplateSpecCandidate &addCandidate() { |
||
362 | Candidates.emplace_back(); |
||
363 | return Candidates.back(); |
||
364 | } |
||
365 | |||
366 | void NoteCandidates(Sema &S, SourceLocation Loc); |
||
367 | |||
368 | void NoteCandidates(Sema &S, SourceLocation Loc) const { |
||
369 | const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc); |
||
370 | } |
||
371 | }; |
||
372 | |||
373 | } // namespace clang |
||
374 | |||
375 | #endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H |