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