Clang Project

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