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