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