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)
Loc(Loc)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.
TemplateDeductionInfo(ForBaseTag,const TemplateDeductionInfo & Info)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.
getLocation()79   SourceLocation getLocation() const {
80     return Loc;
81   }
82 
83   /// The depth of template parameters for which deduction is being
84   /// performed.
getDeducedDepth()85   unsigned getDeducedDepth() const {
86     return DeducedDepth;
87   }
88 
89   /// Get the number of explicitly-specified arguments.
getNumExplicitArgs()90   unsigned getNumExplicitArgs() const {
91     return ExplicitArgs;
92   }
93 
94   /// Take ownership of the deduced template argument lists.
takeSugared()95   TemplateArgumentList *takeSugared() {
96     TemplateArgumentList *Result = DeducedSugared;
97     DeducedSugared = nullptr;
98     return Result;
99   }
takeCanonical()100   TemplateArgumentList *takeCanonical() {
101     TemplateArgumentList *Result = DeducedCanonical;
102     DeducedCanonical = nullptr;
103     return Result;
104   }
105 
106   /// Take ownership of the SFINAE diagnostic.
takeSFINAEDiagnostic(PartialDiagnosticAt & PD)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.
clearSFINAEDiagnostic()115   void clearSFINAEDiagnostic() {
116     SuppressedDiagnostics.clear();
117     HasSFINAEDiagnostic = false;
118   }
119 
120   /// Peek at the SFINAE diagnostic.
peekSFINAEDiagnostic()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.
setExplicitArgs(TemplateArgumentList * NewDeducedSugared,TemplateArgumentList * NewDeducedCanonical)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.
reset(TemplateArgumentList * NewDeducedSugared,TemplateArgumentList * NewDeducedCanonical)138   void reset(TemplateArgumentList *NewDeducedSugared,
139              TemplateArgumentList *NewDeducedCanonical) {
140     DeducedSugared = NewDeducedSugared;
141     DeducedCanonical = NewDeducedCanonical;
142   }
143 
144   /// Is a SFINAE diagnostic available?
hasSFINAEDiagnostic()145   bool hasSFINAEDiagnostic() const {
146     return HasSFINAEDiagnostic;
147   }
148 
149   /// Set the diagnostic which caused the SFINAE failure.
addSFINAEDiagnostic(SourceLocation Loc,PartialDiagnostic PD)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
addSuppressedDiagnostic(SourceLocation Loc,PartialDiagnostic PD)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.
diag_begin()172   diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
173 
174   /// Returns an iterator at the end of the sequence of suppressed
175   /// diagnostics.
diag_end()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   // C++20 [over.match.class.deduct]p5.2:
238   //   During template argument deduction for the aggregate deduction
239   //   candidate, the number of elements in a trailing parameter pack is only
240   //   deduced from the number of remaining function arguments if it is not
241   //   otherwise deduced.
242   bool AggregateDeductionCandidateHasMismatchedArity = false;
243 
244   /// Information on packs that we're currently expanding.
245   ///
246   /// FIXME: This should be kept internal to SemaTemplateDeduction.
247   SmallVector<DeducedPack *, 8> PendingDeducedPacks;
248 
249   /// \brief The constraint satisfaction details resulting from the associated
250   /// constraints satisfaction tests.
251   ConstraintSatisfaction AssociatedConstraintsSatisfaction;
252 };
253 
254 } // namespace sema
255 
256 /// A structure used to record information about a failed
257 /// template argument deduction, for diagnosis.
258 struct DeductionFailureInfo {
259   /// A Sema::TemplateDeductionResult.
260   unsigned Result : 8;
261 
262   /// Indicates whether a diagnostic is stored in Diagnostic.
263   unsigned HasDiagnostic : 1;
264 
265   /// Opaque pointer containing additional data about
266   /// this deduction failure.
267   void *Data;
268 
269   /// A diagnostic indicating why deduction failed.
270   alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)];
271 
272   /// Retrieve the diagnostic which caused this deduction failure,
273   /// if any.
274   PartialDiagnosticAt *getSFINAEDiagnostic();
275 
276   /// Retrieve the template parameter this deduction failure
277   /// refers to, if any.
278   TemplateParameter getTemplateParameter();
279 
280   /// Retrieve the template argument list associated with this
281   /// deduction failure, if any.
282   TemplateArgumentList *getTemplateArgumentList();
283 
284   /// Return the first template argument this deduction failure
285   /// refers to, if any.
286   const TemplateArgument *getFirstArg();
287 
288   /// Return the second template argument this deduction failure
289   /// refers to, if any.
290   const TemplateArgument *getSecondArg();
291 
292   /// Return the index of the call argument that this deduction
293   /// failure refers to, if any.
294   std::optional<unsigned> getCallArgIndex();
295 
296   /// Free any memory associated with this deduction failure.
297   void Destroy();
298 };
299 
300 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate
301 /// which keeps track of template argument deduction failure info, when
302 /// handling explicit specializations (and instantiations) of templates
303 /// beyond function overloading.
304 /// For now, assume that the candidates are non-matching specializations.
305 /// TODO: In the future, we may need to unify/generalize this with
306 /// OverloadCandidate.
307 struct TemplateSpecCandidate {
308   /// The declaration that was looked up, together with its access.
309   /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
310   DeclAccessPair FoundDecl;
311 
312   /// Specialization - The actual specialization that this candidate
313   /// represents. When NULL, this may be a built-in candidate.
314   Decl *Specialization;
315 
316   /// Template argument deduction info
317   DeductionFailureInfo DeductionFailure;
318 
setTemplateSpecCandidate319   void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) {
320     FoundDecl = Found;
321     Specialization = Spec;
322     DeductionFailure = Info;
323   }
324 
325   /// Diagnose a template argument deduction failure.
326   void NoteDeductionFailure(Sema &S, bool ForTakingAddress);
327 };
328 
329 /// TemplateSpecCandidateSet - A set of generalized overload candidates,
330 /// used in template specializations.
331 /// TODO: In the future, we may need to unify/generalize this with
332 /// OverloadCandidateSet.
333 class TemplateSpecCandidateSet {
334   SmallVector<TemplateSpecCandidate, 16> Candidates;
335   SourceLocation Loc;
336 
337   // Stores whether we're taking the address of these candidates. This helps us
338   // produce better error messages when dealing with the pass_object_size
339   // attribute on parameters.
340   bool ForTakingAddress;
341 
342   void destroyCandidates();
343 
344 public:
345   TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
Loc(Loc)346       : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
347   TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
348   TemplateSpecCandidateSet &
349   operator=(const TemplateSpecCandidateSet &) = delete;
~TemplateSpecCandidateSet()350   ~TemplateSpecCandidateSet() { destroyCandidates(); }
351 
getLocation()352   SourceLocation getLocation() const { return Loc; }
353 
354   /// Clear out all of the candidates.
355   /// TODO: This may be unnecessary.
356   void clear();
357 
358   using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator;
359 
begin()360   iterator begin() { return Candidates.begin(); }
end()361   iterator end() { return Candidates.end(); }
362 
size()363   size_t size() const { return Candidates.size(); }
empty()364   bool empty() const { return Candidates.empty(); }
365 
366   /// Add a new candidate with NumConversions conversion sequence slots
367   /// to the overload set.
addCandidate()368   TemplateSpecCandidate &addCandidate() {
369     Candidates.emplace_back();
370     return Candidates.back();
371   }
372 
373   void NoteCandidates(Sema &S, SourceLocation Loc);
374 
NoteCandidates(Sema & S,SourceLocation Loc)375   void NoteCandidates(Sema &S, SourceLocation Loc) const {
376     const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
377   }
378 };
379 
380 } // namespace clang
381 
382 #endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
383