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