1135446Strhodes//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/
2254897Serwin//
3153816Sdougb//                     The LLVM Compiler Infrastructure
4153816Sdougb//
5204619Sdougb// This file is distributed under the University of Illinois Open Source
6135446Strhodes// License. See LICENSE.TXT for details.
7135446Strhodes//===----------------------------------------------------------------------===/
8153816Sdougb//
9135446Strhodes//  This file provides types used with Sema's template argument deduction
10135446Strhodes// routines.
11153816Sdougb//
12135446Strhodes//===----------------------------------------------------------------------===/
13135446Strhodes#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
14135446Strhodes#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
15135446Strhodes
16135446Strhodes#include "clang/AST/DeclTemplate.h"
17234010Sdougb#include "clang/Basic/PartialDiagnostic.h"
18153816Sdougb#include "llvm/ADT/SmallVector.h"
19153816Sdougb
20153816Sdougbnamespace clang {
21153816Sdougb
22170222Sdougbclass TemplateArgumentList;
23153816Sdougbclass Sema;
24153816Sdougb
25225361Sdougbnamespace sema {
26153816Sdougb
27153816Sdougb/// \brief Provides information about an attempted template argument
28153816Sdougb/// deduction, whose success or failure was described by a
29153816Sdougb/// TemplateDeductionResult value.
30153816Sdougbclass TemplateDeductionInfo {
31153816Sdougb  /// \brief The deduced template argument list.
32153816Sdougb  ///
33153816Sdougb  TemplateArgumentList *Deduced;
34170222Sdougb
35153816Sdougb  /// \brief The source location at which template argument
36153816Sdougb  /// deduction is occurring.
37153816Sdougb  SourceLocation Loc;
38170222Sdougb
39153816Sdougb  /// \brief Have we suppressed an error during deduction?
40170222Sdougb  bool HasSFINAEDiagnostic;
41170222Sdougb
42170222Sdougb  /// \brief Warnings (and follow-on notes) that were suppressed due to
43153816Sdougb  /// SFINAE while performing template argument deduction.
44153816Sdougb  SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
45153816Sdougb
46170222Sdougb  TemplateDeductionInfo(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION;
47153816Sdougb  void operator=(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION;
48170222Sdougb
49170222Sdougbpublic:
50153816Sdougb  TemplateDeductionInfo(SourceLocation Loc)
51153816Sdougb    : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { }
52153816Sdougb
53153816Sdougb  /// \brief Returns the location at which template argument is
54153816Sdougb  /// occurring.
55170222Sdougb  SourceLocation getLocation() const {
56170222Sdougb    return Loc;
57170222Sdougb  }
58153816Sdougb
59153816Sdougb  /// \brief Take ownership of the deduced template argument list.
60153816Sdougb  TemplateArgumentList *take() {
61170222Sdougb    TemplateArgumentList *Result = Deduced;
62153816Sdougb    Deduced = 0;
63170222Sdougb    return Result;
64153816Sdougb  }
65153816Sdougb
66153816Sdougb  /// \brief Take ownership of the SFINAE diagnostic.
67153816Sdougb  void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
68153816Sdougb    assert(HasSFINAEDiagnostic);
69153816Sdougb    PD.first = SuppressedDiagnostics.front().first;
70153816Sdougb    PD.second.swap(SuppressedDiagnostics.front().second);
71170222Sdougb    SuppressedDiagnostics.clear();
72170222Sdougb    HasSFINAEDiagnostic = false;
73170222Sdougb  }
74153816Sdougb
75153816Sdougb  /// \brief Provide a new template argument list that contains the
76153816Sdougb  /// results of template argument deduction.
77170222Sdougb  void reset(TemplateArgumentList *NewDeduced) {
78153816Sdougb    Deduced = NewDeduced;
79170222Sdougb  }
80153816Sdougb
81153816Sdougb  /// \brief Is a SFINAE diagnostic available?
82170222Sdougb  bool hasSFINAEDiagnostic() const {
83153816Sdougb    return HasSFINAEDiagnostic;
84153816Sdougb  }
85153816Sdougb
86170222Sdougb  /// \brief Set the diagnostic which caused the SFINAE failure.
87153816Sdougb  void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
88170222Sdougb    // Only collect the first diagnostic.
89170222Sdougb    if (HasSFINAEDiagnostic)
90153816Sdougb      return;
91153816Sdougb    SuppressedDiagnostics.clear();
92153816Sdougb    SuppressedDiagnostics.push_back(
93254897Serwin        std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
94170222Sdougb    SuppressedDiagnostics.back().second.swap(PD);
95170222Sdougb    HasSFINAEDiagnostic = true;
96170222Sdougb  }
97170222Sdougb
98170222Sdougb  /// \brief Add a new diagnostic to the set of diagnostics
99170222Sdougb  void addSuppressedDiagnostic(SourceLocation Loc,
100170222Sdougb                               PartialDiagnostic PD) {
101170222Sdougb    if (HasSFINAEDiagnostic)
102170222Sdougb      return;
103170222Sdougb    SuppressedDiagnostics.push_back(
104170222Sdougb        std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
105170222Sdougb    SuppressedDiagnostics.back().second.swap(PD);
106170222Sdougb  }
107170222Sdougb
108170222Sdougb  /// \brief Iterator over the set of suppressed diagnostics.
109170222Sdougb  typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator
110170222Sdougb    diag_iterator;
111170222Sdougb
112170222Sdougb  /// \brief Returns an iterator at the beginning of the sequence of suppressed
113170222Sdougb  /// diagnostics.
114170222Sdougb  diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
115170222Sdougb
116170222Sdougb  /// \brief Returns an iterator at the end of the sequence of suppressed
117170222Sdougb  /// diagnostics.
118170222Sdougb  diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
119170222Sdougb
120170222Sdougb  /// \brief The template parameter to which a template argument
121170222Sdougb  /// deduction failure refers.
122170222Sdougb  ///
123170222Sdougb  /// Depending on the result of template argument deduction, this
124153816Sdougb  /// template parameter may have different meanings:
125153816Sdougb  ///
126254897Serwin  ///   TDK_Incomplete: this is the first template parameter whose
127170222Sdougb  ///   corresponding template argument was not deduced.
128170222Sdougb  ///
129170222Sdougb  ///   TDK_Inconsistent: this is the template parameter for which
130170222Sdougb  ///   two different template argument values were deduced.
131170222Sdougb  TemplateParameter Param;
132170222Sdougb
133170222Sdougb  /// \brief The first template argument to which the template
134170222Sdougb  /// argument deduction failure refers.
135170222Sdougb  ///
136170222Sdougb  /// Depending on the result of the template argument deduction,
137170222Sdougb  /// this template argument may have different meanings:
138170222Sdougb  ///
139170222Sdougb  ///   TDK_Inconsistent: this argument is the first value deduced
140170222Sdougb  ///   for the corresponding template parameter.
141170222Sdougb  ///
142170222Sdougb  ///   TDK_SubstitutionFailure: this argument is the template
143153816Sdougb  ///   argument we were instantiating when we encountered an error.
144153816Sdougb  ///
145254897Serwin  ///   TDK_NonDeducedMismatch: this is the component of the 'parameter'
146170222Sdougb  ///   of the deduction, directly provided in the source code.
147170222Sdougb  TemplateArgument FirstArg;
148170222Sdougb
149153816Sdougb  /// \brief The second template argument to which the template
150153816Sdougb  /// argument deduction failure refers.
151254897Serwin  ///
152170222Sdougb  ///   TDK_NonDeducedMismatch: this is the mismatching component of the
153170222Sdougb  ///   'argument' of the deduction, from which we are deducing arguments.
154153816Sdougb  ///
155153816Sdougb  /// FIXME: Finish documenting this.
156153816Sdougb  TemplateArgument SecondArg;
157
158  /// \brief The expression which caused a deduction failure.
159  ///
160  ///   TDK_FailedOverloadResolution: this argument is the reference to
161  ///   an overloaded function which could not be resolved to a specific
162  ///   function.
163  Expr *Expression;
164};
165
166} // end namespace sema
167
168/// A structure used to record information about a failed
169/// template argument deduction, for diagnosis.
170struct DeductionFailureInfo {
171  /// A Sema::TemplateDeductionResult.
172  unsigned Result : 8;
173
174  /// \brief Indicates whether a diagnostic is stored in Diagnostic.
175  unsigned HasDiagnostic : 1;
176
177  /// \brief Opaque pointer containing additional data about
178  /// this deduction failure.
179  void *Data;
180
181  /// \brief A diagnostic indicating why deduction failed.
182  union {
183    void *Align;
184    char Diagnostic[sizeof(PartialDiagnosticAt)];
185  };
186
187  /// \brief Retrieve the diagnostic which caused this deduction failure,
188  /// if any.
189  PartialDiagnosticAt *getSFINAEDiagnostic();
190
191  /// \brief Retrieve the template parameter this deduction failure
192  /// refers to, if any.
193  TemplateParameter getTemplateParameter();
194
195  /// \brief Retrieve the template argument list associated with this
196  /// deduction failure, if any.
197  TemplateArgumentList *getTemplateArgumentList();
198
199  /// \brief Return the first template argument this deduction failure
200  /// refers to, if any.
201  const TemplateArgument *getFirstArg();
202
203  /// \brief Return the second template argument this deduction failure
204  /// refers to, if any.
205  const TemplateArgument *getSecondArg();
206
207  /// \brief Return the expression this deduction failure refers to,
208  /// if any.
209  Expr *getExpr();
210
211  /// \brief Free any memory associated with this deduction failure.
212  void Destroy();
213};
214
215/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
216/// which keeps track of template argument deduction failure info, when
217/// handling explicit specializations (and instantiations) of templates
218/// beyond function overloading.
219/// For now, assume that the candidates are non-matching specializations.
220/// TODO: In the future, we may need to unify/generalize this with
221/// OverloadCandidate.
222struct TemplateSpecCandidate {
223  /// Specialization - The actual specialization that this candidate
224  /// represents. When NULL, this may be a built-in candidate.
225  Decl *Specialization;
226
227  /// Template argument deduction info
228  DeductionFailureInfo DeductionFailure;
229
230  void set(Decl *Spec, DeductionFailureInfo Info) {
231    Specialization = Spec;
232    DeductionFailure = Info;
233  }
234
235  /// Diagnose a template argument deduction failure.
236  void NoteDeductionFailure(Sema &S);
237};
238
239/// TemplateSpecCandidateSet - A set of generalized overload candidates,
240/// used in template specializations.
241/// TODO: In the future, we may need to unify/generalize this with
242/// OverloadCandidateSet.
243class TemplateSpecCandidateSet {
244  SmallVector<TemplateSpecCandidate, 16> Candidates;
245  SourceLocation Loc;
246
247  TemplateSpecCandidateSet(
248      const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
249  void operator=(const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
250
251  void destroyCandidates();
252
253public:
254  TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
255  ~TemplateSpecCandidateSet() { destroyCandidates(); }
256
257  SourceLocation getLocation() const { return Loc; }
258
259  /// \brief Clear out all of the candidates.
260  /// TODO: This may be unnecessary.
261  void clear();
262
263  typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
264  iterator begin() { return Candidates.begin(); }
265  iterator end() { return Candidates.end(); }
266
267  size_t size() const { return Candidates.size(); }
268  bool empty() const { return Candidates.empty(); }
269
270  /// \brief Add a new candidate with NumConversions conversion sequence slots
271  /// to the overload set.
272  TemplateSpecCandidate &addCandidate() {
273    Candidates.push_back(TemplateSpecCandidate());
274    return Candidates.back();
275  }
276
277  void NoteCandidates(Sema &S, SourceLocation Loc);
278
279  void NoteCandidates(Sema &S, SourceLocation Loc) const {
280    const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
281  }
282};
283
284} // end namespace clang
285
286#endif
287