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