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