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