1212795Sdim//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/
2212795Sdim//
3212795Sdim//                     The LLVM Compiler Infrastructure
4212795Sdim//
5212795Sdim// This file is distributed under the University of Illinois Open Source
6212795Sdim// License. See LICENSE.TXT for details.
7212795Sdim//===----------------------------------------------------------------------===/
8212795Sdim//
9212795Sdim//  This file provides types used with Sema's template argument deduction
10212795Sdim// routines.
11212795Sdim//
12212795Sdim//===----------------------------------------------------------------------===/
13212795Sdim#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
14212795Sdim#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H
15212795Sdim
16249423Sdim#include "clang/AST/DeclTemplate.h"
17218893Sdim#include "clang/Basic/PartialDiagnostic.h"
18218893Sdim#include "llvm/ADT/SmallVector.h"
19212795Sdim
20212795Sdimnamespace clang {
21212795Sdim
22212795Sdimclass TemplateArgumentList;
23263508Sdimclass Sema;
24212795Sdim
25212795Sdimnamespace sema {
26234353Sdim
27212795Sdim/// \brief Provides information about an attempted template argument
28212795Sdim/// deduction, whose success or failure was described by a
29212795Sdim/// TemplateDeductionResult value.
30212795Sdimclass TemplateDeductionInfo {
31212795Sdim  /// \brief The deduced template argument list.
32212795Sdim  ///
33212795Sdim  TemplateArgumentList *Deduced;
34212795Sdim
35212795Sdim  /// \brief The source location at which template argument
36212795Sdim  /// deduction is occurring.
37212795Sdim  SourceLocation Loc;
38212795Sdim
39239462Sdim  /// \brief Have we suppressed an error during deduction?
40239462Sdim  bool HasSFINAEDiagnostic;
41239462Sdim
42234353Sdim  /// \brief Warnings (and follow-on notes) that were suppressed due to
43218893Sdim  /// SFINAE while performing template argument deduction.
44226633Sdim  SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
45234353Sdim
46243830Sdim  TemplateDeductionInfo(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION;
47243830Sdim  void operator=(const TemplateDeductionInfo &) LLVM_DELETED_FUNCTION;
48212795Sdim
49212795Sdimpublic:
50243830Sdim  TemplateDeductionInfo(SourceLocation Loc)
51249423Sdim    : Deduced(0), Loc(Loc), HasSFINAEDiagnostic(false), Expression(0) { }
52212795Sdim
53212795Sdim  /// \brief Returns the location at which template argument is
54221345Sdim  /// occurring.
55212795Sdim  SourceLocation getLocation() const {
56212795Sdim    return Loc;
57212795Sdim  }
58212795Sdim
59212795Sdim  /// \brief Take ownership of the deduced template argument list.
60212795Sdim  TemplateArgumentList *take() {
61212795Sdim    TemplateArgumentList *Result = Deduced;
62212795Sdim    Deduced = 0;
63212795Sdim    return Result;
64212795Sdim  }
65212795Sdim
66239462Sdim  /// \brief Take ownership of the SFINAE diagnostic.
67239462Sdim  void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
68239462Sdim    assert(HasSFINAEDiagnostic);
69239462Sdim    PD.first = SuppressedDiagnostics.front().first;
70239462Sdim    PD.second.swap(SuppressedDiagnostics.front().second);
71239462Sdim    SuppressedDiagnostics.clear();
72239462Sdim    HasSFINAEDiagnostic = false;
73239462Sdim  }
74239462Sdim
75212795Sdim  /// \brief Provide a new template argument list that contains the
76212795Sdim  /// results of template argument deduction.
77212795Sdim  void reset(TemplateArgumentList *NewDeduced) {
78212795Sdim    Deduced = NewDeduced;
79212795Sdim  }
80212795Sdim
81239462Sdim  /// \brief Is a SFINAE diagnostic available?
82239462Sdim  bool hasSFINAEDiagnostic() const {
83239462Sdim    return HasSFINAEDiagnostic;
84239462Sdim  }
85239462Sdim
86239462Sdim  /// \brief Set the diagnostic which caused the SFINAE failure.
87239462Sdim  void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
88239462Sdim    // Only collect the first diagnostic.
89239462Sdim    if (HasSFINAEDiagnostic)
90239462Sdim      return;
91239462Sdim    SuppressedDiagnostics.clear();
92239462Sdim    SuppressedDiagnostics.push_back(
93239462Sdim        std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
94239462Sdim    SuppressedDiagnostics.back().second.swap(PD);
95239462Sdim    HasSFINAEDiagnostic = true;
96239462Sdim  }
97239462Sdim
98234353Sdim  /// \brief Add a new diagnostic to the set of diagnostics
99234353Sdim  void addSuppressedDiagnostic(SourceLocation Loc,
100239462Sdim                               PartialDiagnostic PD) {
101239462Sdim    if (HasSFINAEDiagnostic)
102239462Sdim      return;
103239462Sdim    SuppressedDiagnostics.push_back(
104239462Sdim        std::make_pair(Loc, PartialDiagnostic::NullDiagnostic()));
105239462Sdim    SuppressedDiagnostics.back().second.swap(PD);
106218893Sdim  }
107234353Sdim
108218893Sdim  /// \brief Iterator over the set of suppressed diagnostics.
109234353Sdim  typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator
110218893Sdim    diag_iterator;
111234353Sdim
112218893Sdim  /// \brief Returns an iterator at the beginning of the sequence of suppressed
113218893Sdim  /// diagnostics.
114218893Sdim  diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
115234353Sdim
116218893Sdim  /// \brief Returns an iterator at the end of the sequence of suppressed
117218893Sdim  /// diagnostics.
118218893Sdim  diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
119234353Sdim
120212795Sdim  /// \brief The template parameter to which a template argument
121212795Sdim  /// deduction failure refers.
122212795Sdim  ///
123212795Sdim  /// Depending on the result of template argument deduction, this
124212795Sdim  /// template parameter may have different meanings:
125212795Sdim  ///
126212795Sdim  ///   TDK_Incomplete: this is the first template parameter whose
127212795Sdim  ///   corresponding template argument was not deduced.
128212795Sdim  ///
129212795Sdim  ///   TDK_Inconsistent: this is the template parameter for which
130212795Sdim  ///   two different template argument values were deduced.
131212795Sdim  TemplateParameter Param;
132212795Sdim
133212795Sdim  /// \brief The first template argument to which the template
134212795Sdim  /// argument deduction failure refers.
135212795Sdim  ///
136212795Sdim  /// Depending on the result of the template argument deduction,
137212795Sdim  /// this template argument may have different meanings:
138212795Sdim  ///
139212795Sdim  ///   TDK_Inconsistent: this argument is the first value deduced
140212795Sdim  ///   for the corresponding template parameter.
141212795Sdim  ///
142212795Sdim  ///   TDK_SubstitutionFailure: this argument is the template
143212795Sdim  ///   argument we were instantiating when we encountered an error.
144212795Sdim  ///
145249423Sdim  ///   TDK_NonDeducedMismatch: this is the component of the 'parameter'
146249423Sdim  ///   of the deduction, directly provided in the source code.
147212795Sdim  TemplateArgument FirstArg;
148212795Sdim
149212795Sdim  /// \brief The second template argument to which the template
150212795Sdim  /// argument deduction failure refers.
151212795Sdim  ///
152249423Sdim  ///   TDK_NonDeducedMismatch: this is the mismatching component of the
153249423Sdim  ///   'argument' of the deduction, from which we are deducing arguments.
154249423Sdim  ///
155212795Sdim  /// FIXME: Finish documenting this.
156212795Sdim  TemplateArgument SecondArg;
157249423Sdim
158249423Sdim  /// \brief The expression which caused a deduction failure.
159249423Sdim  ///
160249423Sdim  ///   TDK_FailedOverloadResolution: this argument is the reference to
161251662Sdim  ///   an overloaded function which could not be resolved to a specific
162251662Sdim  ///   function.
163249423Sdim  Expr *Expression;
164212795Sdim};
165212795Sdim
166263508Sdim} // end namespace sema
167212795Sdim
168263508Sdim/// A structure used to record information about a failed
169263508Sdim/// template argument deduction, for diagnosis.
170263508Sdimstruct DeductionFailureInfo {
171263508Sdim  /// A Sema::TemplateDeductionResult.
172263508Sdim  unsigned Result : 8;
173263508Sdim
174263508Sdim  /// \brief Indicates whether a diagnostic is stored in Diagnostic.
175263508Sdim  unsigned HasDiagnostic : 1;
176263508Sdim
177263508Sdim  /// \brief Opaque pointer containing additional data about
178263508Sdim  /// this deduction failure.
179263508Sdim  void *Data;
180263508Sdim
181263508Sdim  /// \brief A diagnostic indicating why deduction failed.
182263508Sdim  union {
183263508Sdim    void *Align;
184263508Sdim    char Diagnostic[sizeof(PartialDiagnosticAt)];
185263508Sdim  };
186263508Sdim
187263508Sdim  /// \brief Retrieve the diagnostic which caused this deduction failure,
188263508Sdim  /// if any.
189263508Sdim  PartialDiagnosticAt *getSFINAEDiagnostic();
190263508Sdim
191263508Sdim  /// \brief Retrieve the template parameter this deduction failure
192263508Sdim  /// refers to, if any.
193263508Sdim  TemplateParameter getTemplateParameter();
194263508Sdim
195263508Sdim  /// \brief Retrieve the template argument list associated with this
196263508Sdim  /// deduction failure, if any.
197263508Sdim  TemplateArgumentList *getTemplateArgumentList();
198263508Sdim
199263508Sdim  /// \brief Return the first template argument this deduction failure
200263508Sdim  /// refers to, if any.
201263508Sdim  const TemplateArgument *getFirstArg();
202263508Sdim
203263508Sdim  /// \brief Return the second template argument this deduction failure
204263508Sdim  /// refers to, if any.
205263508Sdim  const TemplateArgument *getSecondArg();
206263508Sdim
207263508Sdim  /// \brief Return the expression this deduction failure refers to,
208263508Sdim  /// if any.
209263508Sdim  Expr *getExpr();
210263508Sdim
211263508Sdim  /// \brief Free any memory associated with this deduction failure.
212263508Sdim  void Destroy();
213263508Sdim};
214263508Sdim
215263508Sdim/// TemplateSpecCandidate - This is a generalization of OverloadCandidate
216263508Sdim/// which keeps track of template argument deduction failure info, when
217263508Sdim/// handling explicit specializations (and instantiations) of templates
218263508Sdim/// beyond function overloading.
219263508Sdim/// For now, assume that the candidates are non-matching specializations.
220263508Sdim/// TODO: In the future, we may need to unify/generalize this with
221263508Sdim/// OverloadCandidate.
222263508Sdimstruct TemplateSpecCandidate {
223263508Sdim  /// Specialization - The actual specialization that this candidate
224263508Sdim  /// represents. When NULL, this may be a built-in candidate.
225263508Sdim  Decl *Specialization;
226263508Sdim
227263508Sdim  /// Template argument deduction info
228263508Sdim  DeductionFailureInfo DeductionFailure;
229263508Sdim
230263508Sdim  void set(Decl *Spec, DeductionFailureInfo Info) {
231263508Sdim    Specialization = Spec;
232263508Sdim    DeductionFailure = Info;
233263508Sdim  }
234263508Sdim
235263508Sdim  /// Diagnose a template argument deduction failure.
236263508Sdim  void NoteDeductionFailure(Sema &S);
237263508Sdim};
238263508Sdim
239263508Sdim/// TemplateSpecCandidateSet - A set of generalized overload candidates,
240263508Sdim/// used in template specializations.
241263508Sdim/// TODO: In the future, we may need to unify/generalize this with
242263508Sdim/// OverloadCandidateSet.
243263508Sdimclass TemplateSpecCandidateSet {
244263508Sdim  SmallVector<TemplateSpecCandidate, 16> Candidates;
245263508Sdim  SourceLocation Loc;
246263508Sdim
247263508Sdim  TemplateSpecCandidateSet(
248263508Sdim      const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
249263508Sdim  void operator=(const TemplateSpecCandidateSet &) LLVM_DELETED_FUNCTION;
250263508Sdim
251263508Sdim  void destroyCandidates();
252263508Sdim
253263508Sdimpublic:
254263508Sdim  TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {}
255263508Sdim  ~TemplateSpecCandidateSet() { destroyCandidates(); }
256263508Sdim
257263508Sdim  SourceLocation getLocation() const { return Loc; }
258263508Sdim
259263508Sdim  /// \brief Clear out all of the candidates.
260263508Sdim  /// TODO: This may be unnecessary.
261263508Sdim  void clear();
262263508Sdim
263263508Sdim  typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator;
264263508Sdim  iterator begin() { return Candidates.begin(); }
265263508Sdim  iterator end() { return Candidates.end(); }
266263508Sdim
267263508Sdim  size_t size() const { return Candidates.size(); }
268263508Sdim  bool empty() const { return Candidates.empty(); }
269263508Sdim
270263508Sdim  /// \brief Add a new candidate with NumConversions conversion sequence slots
271263508Sdim  /// to the overload set.
272263508Sdim  TemplateSpecCandidate &addCandidate() {
273263508Sdim    Candidates.push_back(TemplateSpecCandidate());
274263508Sdim    return Candidates.back();
275263508Sdim  }
276263508Sdim
277263508Sdim  void NoteCandidates(Sema &S, SourceLocation Loc);
278263508Sdim
279263508Sdim  void NoteCandidates(Sema &S, SourceLocation Loc) const {
280263508Sdim    const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
281263508Sdim  }
282263508Sdim};
283263508Sdim
284263508Sdim} // end namespace clang
285263508Sdim
286212795Sdim#endif
287