xref: /freebsd/contrib/llvm-project/clang/include/clang/Sema/TemplateDeduction.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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)
Loc(Loc)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.
TemplateDeductionInfo(ForBaseTag,const TemplateDeductionInfo & Info)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.
getLocation()80   SourceLocation getLocation() const {
81     return Loc;
82   }
83 
84   /// The depth of template parameters for which deduction is being
85   /// performed.
getDeducedDepth()86   unsigned getDeducedDepth() const {
87     return DeducedDepth;
88   }
89 
90   /// Get the number of explicitly-specified arguments.
getNumExplicitArgs()91   unsigned getNumExplicitArgs() const {
92     return ExplicitArgs;
93   }
94 
95   /// Take ownership of the deduced template argument lists.
takeSugared()96   TemplateArgumentList *takeSugared() {
97     TemplateArgumentList *Result = DeducedSugared;
98     DeducedSugared = nullptr;
99     return Result;
100   }
takeCanonical()101   TemplateArgumentList *takeCanonical() {
102     TemplateArgumentList *Result = DeducedCanonical;
103     DeducedCanonical = nullptr;
104     return Result;
105   }
106 
107   /// Take ownership of the SFINAE diagnostic.
takeSFINAEDiagnostic(PartialDiagnosticAt & PD)108   void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
109     assert(HasSFINAEDiagnostic);
110     PD.first = SuppressedDiagnostics.front().first;
111     PD.second.swap(SuppressedDiagnostics.front().second);
112     clearSFINAEDiagnostic();
113   }
114 
115   /// Discard any SFINAE diagnostics.
clearSFINAEDiagnostic()116   void clearSFINAEDiagnostic() {
117     SuppressedDiagnostics.clear();
118     HasSFINAEDiagnostic = false;
119   }
120 
121   /// Peek at the SFINAE diagnostic.
peekSFINAEDiagnostic()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.
setExplicitArgs(TemplateArgumentList * NewDeducedSugared,TemplateArgumentList * NewDeducedCanonical)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.
reset(TemplateArgumentList * NewDeducedSugared,TemplateArgumentList * NewDeducedCanonical)139   void reset(TemplateArgumentList *NewDeducedSugared,
140              TemplateArgumentList *NewDeducedCanonical) {
141     DeducedSugared = NewDeducedSugared;
142     DeducedCanonical = NewDeducedCanonical;
143   }
144 
145   /// Is a SFINAE diagnostic available?
hasSFINAEDiagnostic()146   bool hasSFINAEDiagnostic() const {
147     return HasSFINAEDiagnostic;
148   }
149 
150   /// Set the diagnostic which caused the SFINAE failure.
addSFINAEDiagnostic(SourceLocation Loc,PartialDiagnostic PD)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(Loc, std::move(PD));
157     HasSFINAEDiagnostic = true;
158   }
159 
160   /// Add a new diagnostic to the set of diagnostics
addSuppressedDiagnostic(SourceLocation Loc,PartialDiagnostic PD)161   void addSuppressedDiagnostic(SourceLocation Loc,
162                                PartialDiagnostic PD) {
163     if (HasSFINAEDiagnostic)
164       return;
165     SuppressedDiagnostics.emplace_back(Loc, 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.
diag_begin()173   diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
174 
175   /// Returns an iterator at the end of the sequence of suppressed
176   /// diagnostics.
diag_end()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 
getResultDeductionFailureInfo300   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 
setTemplateSpecCandidate324   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)
Loc(Loc)351       : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
352   TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
353   TemplateSpecCandidateSet &
354   operator=(const TemplateSpecCandidateSet &) = delete;
~TemplateSpecCandidateSet()355   ~TemplateSpecCandidateSet() { destroyCandidates(); }
356 
getLocation()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 
begin()365   iterator begin() { return Candidates.begin(); }
end()366   iterator end() { return Candidates.end(); }
367 
size()368   size_t size() const { return Candidates.size(); }
empty()369   bool empty() const { return Candidates.empty(); }
370 
371   /// Add a new candidate with NumConversions conversion sequence slots
372   /// to the overload set.
addCandidate()373   TemplateSpecCandidate &addCandidate() {
374     Candidates.emplace_back();
375     return Candidates.back();
376   }
377 
378   void NoteCandidates(Sema &S, SourceLocation Loc);
379 
NoteCandidates(Sema & S,SourceLocation Loc)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