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