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