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 // This file provides types used with Sema's template argument deduction 10 // routines. 11 // 12 //===----------------------------------------------------------------------===/ 13 #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 14 #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 15 16 #include "clang/AST/DeclTemplate.h" 17 #include "clang/Basic/PartialDiagnostic.h" 18 #include "llvm/ADT/SmallVector.h" 19 20 namespace clang { 21 22 struct DeducedPack; 23 class TemplateArgumentList; 24 class Sema; 25 26 namespace sema { 27 28 /// \brief Provides information about an attempted template argument 29 /// deduction, whose success or failure was described by a 30 /// TemplateDeductionResult value. 31 class TemplateDeductionInfo { 32 /// \brief The deduced template argument list. 33 /// 34 TemplateArgumentList *Deduced; 35 36 /// \brief The source location at which template argument 37 /// deduction is occurring. 38 SourceLocation Loc; 39 40 /// \brief Have we suppressed an error during deduction? 41 bool HasSFINAEDiagnostic; 42 43 /// \brief Warnings (and follow-on notes) that were suppressed due to 44 /// SFINAE while performing template argument deduction. 45 SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; 46 47 TemplateDeductionInfo(const TemplateDeductionInfo &) = delete; 48 void operator=(const TemplateDeductionInfo &) = delete; 49 50 public: TemplateDeductionInfo(SourceLocation Loc)51 TemplateDeductionInfo(SourceLocation Loc) 52 : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false), 53 Expression(nullptr) {} 54 55 /// \brief Returns the location at which template argument is 56 /// occurring. getLocation()57 SourceLocation getLocation() const { 58 return Loc; 59 } 60 61 /// \brief Take ownership of the deduced template argument list. take()62 TemplateArgumentList *take() { 63 TemplateArgumentList *Result = Deduced; 64 Deduced = nullptr; 65 return Result; 66 } 67 68 /// \brief Take ownership of the SFINAE diagnostic. takeSFINAEDiagnostic(PartialDiagnosticAt & PD)69 void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) { 70 assert(HasSFINAEDiagnostic); 71 PD.first = SuppressedDiagnostics.front().first; 72 PD.second.swap(SuppressedDiagnostics.front().second); 73 SuppressedDiagnostics.clear(); 74 HasSFINAEDiagnostic = false; 75 } 76 77 /// \brief Provide a new template argument list that contains the 78 /// results of template argument deduction. reset(TemplateArgumentList * NewDeduced)79 void reset(TemplateArgumentList *NewDeduced) { 80 Deduced = NewDeduced; 81 } 82 83 /// \brief Is a SFINAE diagnostic available? hasSFINAEDiagnostic()84 bool hasSFINAEDiagnostic() const { 85 return HasSFINAEDiagnostic; 86 } 87 88 /// \brief Set the diagnostic which caused the SFINAE failure. addSFINAEDiagnostic(SourceLocation Loc,PartialDiagnostic PD)89 void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { 90 // Only collect the first diagnostic. 91 if (HasSFINAEDiagnostic) 92 return; 93 SuppressedDiagnostics.clear(); 94 SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); 95 HasSFINAEDiagnostic = true; 96 } 97 98 /// \brief Add a new diagnostic to the set of diagnostics addSuppressedDiagnostic(SourceLocation Loc,PartialDiagnostic PD)99 void addSuppressedDiagnostic(SourceLocation Loc, 100 PartialDiagnostic PD) { 101 if (HasSFINAEDiagnostic) 102 return; 103 SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); 104 } 105 106 /// \brief Iterator over the set of suppressed diagnostics. 107 typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator 108 diag_iterator; 109 110 /// \brief Returns an iterator at the beginning of the sequence of suppressed 111 /// diagnostics. diag_begin()112 diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); } 113 114 /// \brief Returns an iterator at the end of the sequence of suppressed 115 /// diagnostics. diag_end()116 diag_iterator diag_end() const { return SuppressedDiagnostics.end(); } 117 118 /// \brief The template parameter to which a template argument 119 /// deduction failure refers. 120 /// 121 /// Depending on the result of template argument deduction, this 122 /// template parameter may have different meanings: 123 /// 124 /// TDK_Incomplete: this is the first template parameter whose 125 /// corresponding template argument was not deduced. 126 /// 127 /// TDK_Inconsistent: this is the template parameter for which 128 /// two different template argument values were deduced. 129 TemplateParameter Param; 130 131 /// \brief The first template argument to which the template 132 /// argument deduction failure refers. 133 /// 134 /// Depending on the result of the template argument deduction, 135 /// this template argument may have different meanings: 136 /// 137 /// TDK_Inconsistent: this argument is the first value deduced 138 /// for the corresponding template parameter. 139 /// 140 /// TDK_SubstitutionFailure: this argument is the template 141 /// argument we were instantiating when we encountered an error. 142 /// 143 /// TDK_NonDeducedMismatch: this is the component of the 'parameter' 144 /// of the deduction, directly provided in the source code. 145 TemplateArgument FirstArg; 146 147 /// \brief The second template argument to which the template 148 /// argument deduction failure refers. 149 /// 150 /// TDK_NonDeducedMismatch: this is the mismatching component of the 151 /// 'argument' of the deduction, from which we are deducing arguments. 152 /// 153 /// FIXME: Finish documenting this. 154 TemplateArgument SecondArg; 155 156 /// \brief The expression which caused a deduction failure. 157 /// 158 /// TDK_FailedOverloadResolution: this argument is the reference to 159 /// an overloaded function which could not be resolved to a specific 160 /// function. 161 Expr *Expression; 162 163 /// \brief Information on packs that we're currently expanding. 164 /// 165 /// FIXME: This should be kept internal to SemaTemplateDeduction. 166 SmallVector<DeducedPack *, 8> PendingDeducedPacks; 167 }; 168 169 } // end namespace sema 170 171 /// A structure used to record information about a failed 172 /// template argument deduction, for diagnosis. 173 struct DeductionFailureInfo { 174 /// A Sema::TemplateDeductionResult. 175 unsigned Result : 8; 176 177 /// \brief Indicates whether a diagnostic is stored in Diagnostic. 178 unsigned HasDiagnostic : 1; 179 180 /// \brief Opaque pointer containing additional data about 181 /// this deduction failure. 182 void *Data; 183 184 /// \brief A diagnostic indicating why deduction failed. 185 union { 186 void *Align; 187 char Diagnostic[sizeof(PartialDiagnosticAt)]; 188 }; 189 190 /// \brief Retrieve the diagnostic which caused this deduction failure, 191 /// if any. 192 PartialDiagnosticAt *getSFINAEDiagnostic(); 193 194 /// \brief Retrieve the template parameter this deduction failure 195 /// refers to, if any. 196 TemplateParameter getTemplateParameter(); 197 198 /// \brief Retrieve the template argument list associated with this 199 /// deduction failure, if any. 200 TemplateArgumentList *getTemplateArgumentList(); 201 202 /// \brief Return the first template argument this deduction failure 203 /// refers to, if any. 204 const TemplateArgument *getFirstArg(); 205 206 /// \brief Return the second template argument this deduction failure 207 /// refers to, if any. 208 const TemplateArgument *getSecondArg(); 209 210 /// \brief Return the expression this deduction failure refers to, 211 /// if any. 212 Expr *getExpr(); 213 214 /// \brief Free any memory associated with this deduction failure. 215 void Destroy(); 216 }; 217 218 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate 219 /// which keeps track of template argument deduction failure info, when 220 /// handling explicit specializations (and instantiations) of templates 221 /// beyond function overloading. 222 /// For now, assume that the candidates are non-matching specializations. 223 /// TODO: In the future, we may need to unify/generalize this with 224 /// OverloadCandidate. 225 struct TemplateSpecCandidate { 226 /// Specialization - The actual specialization that this candidate 227 /// represents. When NULL, this may be a built-in candidate. 228 Decl *Specialization; 229 230 /// Template argument deduction info 231 DeductionFailureInfo DeductionFailure; 232 setTemplateSpecCandidate233 void set(Decl *Spec, DeductionFailureInfo Info) { 234 Specialization = Spec; 235 DeductionFailure = Info; 236 } 237 238 /// Diagnose a template argument deduction failure. 239 void NoteDeductionFailure(Sema &S); 240 }; 241 242 /// TemplateSpecCandidateSet - A set of generalized overload candidates, 243 /// used in template specializations. 244 /// TODO: In the future, we may need to unify/generalize this with 245 /// OverloadCandidateSet. 246 class TemplateSpecCandidateSet { 247 SmallVector<TemplateSpecCandidate, 16> Candidates; 248 SourceLocation Loc; 249 250 TemplateSpecCandidateSet( 251 const TemplateSpecCandidateSet &) = delete; 252 void operator=(const TemplateSpecCandidateSet &) = delete; 253 254 void destroyCandidates(); 255 256 public: TemplateSpecCandidateSet(SourceLocation Loc)257 TemplateSpecCandidateSet(SourceLocation Loc) : Loc(Loc) {} ~TemplateSpecCandidateSet()258 ~TemplateSpecCandidateSet() { destroyCandidates(); } 259 getLocation()260 SourceLocation getLocation() const { return Loc; } 261 262 /// \brief Clear out all of the candidates. 263 /// TODO: This may be unnecessary. 264 void clear(); 265 266 typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator; begin()267 iterator begin() { return Candidates.begin(); } end()268 iterator end() { return Candidates.end(); } 269 size()270 size_t size() const { return Candidates.size(); } empty()271 bool empty() const { return Candidates.empty(); } 272 273 /// \brief Add a new candidate with NumConversions conversion sequence slots 274 /// to the overload set. addCandidate()275 TemplateSpecCandidate &addCandidate() { 276 Candidates.emplace_back(); 277 return Candidates.back(); 278 } 279 280 void NoteCandidates(Sema &S, SourceLocation Loc); 281 NoteCandidates(Sema & S,SourceLocation Loc)282 void NoteCandidates(Sema &S, SourceLocation Loc) const { 283 const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc); 284 } 285 }; 286 287 } // end namespace clang 288 289 #endif 290