clang  19.0.0git
TemplateDeduction.h
Go to the documentation of this file.
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"
21 #include "clang/AST/DeclTemplate.h"
22 #include "clang/AST/TemplateBase.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.
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)
67  : Loc(Loc), DeducedDepth(DeducedDepth) {}
70 
71  enum ForBaseTag { ForBase };
72  /// Create temporary template deduction info for speculatively deducing
73  /// against a base class of an argument's type.
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.
81  return Loc;
82  }
83 
84  /// The depth of template parameters for which deduction is being
85  /// performed.
86  unsigned getDeducedDepth() const {
87  return DeducedDepth;
88  }
89 
90  /// Get the number of explicitly-specified arguments.
91  unsigned getNumExplicitArgs() const {
92  return ExplicitArgs;
93  }
94 
95  /// Take ownership of the deduced template argument lists.
97  TemplateArgumentList *Result = DeducedSugared;
98  DeducedSugared = nullptr;
99  return Result;
100  }
102  TemplateArgumentList *Result = DeducedCanonical;
103  DeducedCanonical = nullptr;
104  return Result;
105  }
106 
107  /// Take ownership of the SFINAE diagnostic.
109  assert(HasSFINAEDiagnostic);
110  PD.first = SuppressedDiagnostics.front().first;
111  PD.second.swap(SuppressedDiagnostics.front().second);
113  }
114 
115  /// Discard any SFINAE diagnostics.
117  SuppressedDiagnostics.clear();
118  HasSFINAEDiagnostic = false;
119  }
120 
121  /// Peek at the SFINAE diagnostic.
123  assert(HasSFINAEDiagnostic);
124  return SuppressedDiagnostics.front();
125  }
126 
127  /// Provide an initial template argument list that contains the
128  /// explicitly-specified arguments.
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.
139  void reset(TemplateArgumentList *NewDeducedSugared,
140  TemplateArgumentList *NewDeducedCanonical) {
141  DeducedSugared = NewDeducedSugared;
142  DeducedCanonical = NewDeducedCanonical;
143  }
144 
145  /// Is a SFINAE diagnostic available?
146  bool hasSFINAEDiagnostic() const {
147  return HasSFINAEDiagnostic;
148  }
149 
150  /// Set the diagnostic which caused the SFINAE failure.
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
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.
170 
171  /// Returns an iterator at the beginning of the sequence of suppressed
172  /// diagnostics.
173  diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
174 
175  /// Returns an iterator at the end of the sequence of suppressed
176  /// diagnostics.
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.
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.
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.
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.
244 
245  /// Information on packs that we're currently expanding.
246  ///
247  /// FIXME: This should be kept internal to SemaTemplateDeduction.
249 
250  /// \brief The constraint satisfaction details resulting from the associated
251  /// constraints satisfaction tests.
253 };
254 
255 } // namespace sema
256 
257 /// A structure used to record information about a failed
258 /// template argument deduction, for diagnosis.
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.
272 
273  /// Retrieve the diagnostic which caused this deduction failure,
274  /// if any.
276 
277  /// Retrieve the template parameter this deduction failure
278  /// refers to, if any.
280 
281  /// Retrieve the template argument list associated with this
282  /// deduction failure, if any.
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.
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 
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.
313  /// The declaration that was looked up, together with its access.
314  /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
316 
317  /// Specialization - The actual specialization that this candidate
318  /// represents. When NULL, this may be a built-in candidate.
320 
321  /// Template argument deduction info
323 
324  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.
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)
351  : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
355  ~TemplateSpecCandidateSet() { destroyCandidates(); }
356 
357  SourceLocation getLocation() const { return Loc; }
358 
359  /// Clear out all of the candidates.
360  /// TODO: This may be unnecessary.
361  void clear();
362 
364 
365  iterator begin() { return Candidates.begin(); }
366  iterator end() { return Candidates.end(); }
367 
368  size_t size() const { return Candidates.size(); }
369  bool empty() const { return Candidates.empty(); }
370 
371  /// Add a new candidate with NumConversions conversion sequence slots
372  /// to the overload set.
374  Candidates.emplace_back();
375  return Candidates.back();
376  }
377 
378  void NoteCandidates(Sema &S, SourceLocation Loc);
379 
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
This file provides AST data structures related to concepts.
Defines the C++ template declaration subclasses.
Implements a partial diagnostic that can be emitted anwyhere in a DiagnosticBuilder stream.
SourceLocation Loc
Definition: SemaObjC.cpp:755
Defines the clang::SourceLocation class and associated facilities.
The result of a constraint satisfaction check, containing the necessary information to diagnose an un...
Definition: ASTConcept.h:35
A POD class for pairing a NamedDecl* with an access specifier.
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1577
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:462
Encodes a location in the source.
A template argument list.
Definition: DeclTemplate.h:244
unsigned size() const
Retrieve the number of template arguments in this template argument list.
Definition: DeclTemplate.h:280
Represents a template argument.
Definition: TemplateBase.h:61
TemplateSpecCandidateSet - A set of generalized overload candidates, used in template specializations...
SmallVector< TemplateSpecCandidate, 16 >::iterator iterator
void NoteCandidates(Sema &S, SourceLocation Loc)
NoteCandidates - When no template specialization match is found, prints diagnostic messages containin...
void clear()
Clear out all of the candidates.
SourceLocation getLocation() const
TemplateSpecCandidateSet(const TemplateSpecCandidateSet &)=delete
TemplateSpecCandidateSet & operator=(const TemplateSpecCandidateSet &)=delete
TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress=false)
void NoteCandidates(Sema &S, SourceLocation Loc) const
TemplateSpecCandidate & addCandidate()
Add a new candidate with NumConversions conversion sequence slots to the overload set.
Provides information about an attempted template argument deduction, whose success or failure was des...
void setExplicitArgs(TemplateArgumentList *NewDeducedSugared, TemplateArgumentList *NewDeducedCanonical)
Provide an initial template argument list that contains the explicitly-specified arguments.
TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info)
Create temporary template deduction info for speculatively deducing against a base class of an argume...
unsigned getNumExplicitArgs() const
Get the number of explicitly-specified arguments.
SourceLocation getLocation() const
Returns the location at which template argument is occurring.
void addSuppressedDiagnostic(SourceLocation Loc, PartialDiagnostic PD)
Add a new diagnostic to the set of diagnostics.
void clearSFINAEDiagnostic()
Discard any SFINAE diagnostics.
TemplateArgumentList * takeCanonical()
TemplateArgument SecondArg
The second template argument to which the template argument deduction failure refers.
TemplateDeductionInfo & operator=(const TemplateDeductionInfo &)=delete
const PartialDiagnosticAt & peekSFINAEDiagnostic() const
Peek at the SFINAE diagnostic.
TemplateParameter Param
The template parameter to which a template argument deduction failure refers.
diag_iterator diag_end() const
Returns an iterator at the end of the sequence of suppressed diagnostics.
SmallVectorImpl< PartialDiagnosticAt >::const_iterator diag_iterator
Iterator over the set of suppressed diagnostics.
TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth=0)
void reset(TemplateArgumentList *NewDeducedSugared, TemplateArgumentList *NewDeducedCanonical)
Provide a new template argument list that contains the results of template argument deduction.
void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD)
Set the diagnostic which caused the SFINAE failure.
unsigned getDeducedDepth() const
The depth of template parameters for which deduction is being performed.
diag_iterator diag_begin() const
Returns an iterator at the beginning of the sequence of suppressed diagnostics.
bool hasSFINAEDiagnostic() const
Is a SFINAE diagnostic available?
SmallVector< DeducedPack *, 8 > PendingDeducedPacks
Information on packs that we're currently expanding.
TemplateArgument FirstArg
The first template argument to which the template argument deduction failure refers.
ConstraintSatisfaction AssociatedConstraintsSatisfaction
The constraint satisfaction details resulting from the associated constraints satisfaction tests.
TemplateDeductionInfo(const TemplateDeductionInfo &)=delete
void takeSFINAEDiagnostic(PartialDiagnosticAt &PD)
Take ownership of the SFINAE diagnostic.
TemplateArgumentList * takeSugared()
Take ownership of the deduced template argument lists.
unsigned CallArgIndex
The index of the function argument that caused a deduction failure.
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
The JSON file list parser is used to communicate input to InstallAPI.
llvm::PointerUnion< TemplateTypeParmDecl *, NonTypeTemplateParmDecl *, TemplateTemplateParmDecl * > TemplateParameter
Stores a template parameter of any kind.
Definition: DeclTemplate.h:65
std::pair< SourceLocation, PartialDiagnostic > PartialDiagnosticAt
A partial diagnostic along with the source location where this diagnostic occurs.
TemplateDeductionResult
Describes the result of template argument deduction.
Definition: Sema.h:371
A structure used to record information about a failed template argument deduction,...
void * Data
Opaque pointer containing additional data about this deduction failure.
const TemplateArgument * getSecondArg()
Return the second template argument this deduction failure refers to, if any.
unsigned Result
A Sema::TemplateDeductionResult.
PartialDiagnosticAt * getSFINAEDiagnostic()
Retrieve the diagnostic which caused this deduction failure, if any.
std::optional< unsigned > getCallArgIndex()
Return the index of the call argument that this deduction failure refers to, if any.
unsigned HasDiagnostic
Indicates whether a diagnostic is stored in Diagnostic.
TemplateDeductionResult getResult() const
void Destroy()
Free any memory associated with this deduction failure.
TemplateParameter getTemplateParameter()
Retrieve the template parameter this deduction failure refers to, if any.
TemplateArgumentList * getTemplateArgumentList()
Retrieve the template argument list associated with this deduction failure, if any.
const TemplateArgument * getFirstArg()
Return the first template argument this deduction failure refers to, if any.
TemplateSpecCandidate - This is a generalization of OverloadCandidate which keeps track of template a...
void NoteDeductionFailure(Sema &S, bool ForTakingAddress)
Diagnose a template argument deduction failure.
DeductionFailureInfo DeductionFailure
Template argument deduction info.
Decl * Specialization
Specialization - The actual specialization that this candidate represents.
DeclAccessPair FoundDecl
The declaration that was looked up, together with its access.
void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info)