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