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 /// Information on packs that we're currently expanding. 238 /// 239 /// FIXME: This should be kept internal to SemaTemplateDeduction. 240 SmallVector<DeducedPack *, 8> PendingDeducedPacks; 241 242 /// \brief The constraint satisfaction details resulting from the associated 243 /// constraints satisfaction tests. 244 ConstraintSatisfaction AssociatedConstraintsSatisfaction; 245 }; 246 247 } // namespace sema 248 249 /// A structure used to record information about a failed 250 /// template argument deduction, for diagnosis. 251 struct DeductionFailureInfo { 252 /// A Sema::TemplateDeductionResult. 253 unsigned Result : 8; 254 255 /// Indicates whether a diagnostic is stored in Diagnostic. 256 unsigned HasDiagnostic : 1; 257 258 /// Opaque pointer containing additional data about 259 /// this deduction failure. 260 void *Data; 261 262 /// A diagnostic indicating why deduction failed. 263 alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)]; 264 265 /// Retrieve the diagnostic which caused this deduction failure, 266 /// if any. 267 PartialDiagnosticAt *getSFINAEDiagnostic(); 268 269 /// Retrieve the template parameter this deduction failure 270 /// refers to, if any. 271 TemplateParameter getTemplateParameter(); 272 273 /// Retrieve the template argument list associated with this 274 /// deduction failure, if any. 275 TemplateArgumentList *getTemplateArgumentList(); 276 277 /// Return the first template argument this deduction failure 278 /// refers to, if any. 279 const TemplateArgument *getFirstArg(); 280 281 /// Return the second template argument this deduction failure 282 /// refers to, if any. 283 const TemplateArgument *getSecondArg(); 284 285 /// Return the index of the call argument that this deduction 286 /// failure refers to, if any. 287 std::optional<unsigned> getCallArgIndex(); 288 289 /// Free any memory associated with this deduction failure. 290 void Destroy(); 291 }; 292 293 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate 294 /// which keeps track of template argument deduction failure info, when 295 /// handling explicit specializations (and instantiations) of templates 296 /// beyond function overloading. 297 /// For now, assume that the candidates are non-matching specializations. 298 /// TODO: In the future, we may need to unify/generalize this with 299 /// OverloadCandidate. 300 struct TemplateSpecCandidate { 301 /// The declaration that was looked up, together with its access. 302 /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl. 303 DeclAccessPair FoundDecl; 304 305 /// Specialization - The actual specialization that this candidate 306 /// represents. When NULL, this may be a built-in candidate. 307 Decl *Specialization; 308 309 /// Template argument deduction info 310 DeductionFailureInfo DeductionFailure; 311 setTemplateSpecCandidate312 void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) { 313 FoundDecl = Found; 314 Specialization = Spec; 315 DeductionFailure = Info; 316 } 317 318 /// Diagnose a template argument deduction failure. 319 void NoteDeductionFailure(Sema &S, bool ForTakingAddress); 320 }; 321 322 /// TemplateSpecCandidateSet - A set of generalized overload candidates, 323 /// used in template specializations. 324 /// TODO: In the future, we may need to unify/generalize this with 325 /// OverloadCandidateSet. 326 class TemplateSpecCandidateSet { 327 SmallVector<TemplateSpecCandidate, 16> Candidates; 328 SourceLocation Loc; 329 330 // Stores whether we're taking the address of these candidates. This helps us 331 // produce better error messages when dealing with the pass_object_size 332 // attribute on parameters. 333 bool ForTakingAddress; 334 335 void destroyCandidates(); 336 337 public: 338 TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false) Loc(Loc)339 : Loc(Loc), ForTakingAddress(ForTakingAddress) {} 340 TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete; 341 TemplateSpecCandidateSet & 342 operator=(const TemplateSpecCandidateSet &) = delete; ~TemplateSpecCandidateSet()343 ~TemplateSpecCandidateSet() { destroyCandidates(); } 344 getLocation()345 SourceLocation getLocation() const { return Loc; } 346 347 /// Clear out all of the candidates. 348 /// TODO: This may be unnecessary. 349 void clear(); 350 351 using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator; 352 begin()353 iterator begin() { return Candidates.begin(); } end()354 iterator end() { return Candidates.end(); } 355 size()356 size_t size() const { return Candidates.size(); } empty()357 bool empty() const { return Candidates.empty(); } 358 359 /// Add a new candidate with NumConversions conversion sequence slots 360 /// to the overload set. addCandidate()361 TemplateSpecCandidate &addCandidate() { 362 Candidates.emplace_back(); 363 return Candidates.back(); 364 } 365 366 void NoteCandidates(Sema &S, SourceLocation Loc); 367 NoteCandidates(Sema & S,SourceLocation Loc)368 void NoteCandidates(Sema &S, SourceLocation Loc) const { 369 const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc); 370 } 371 }; 372 373 } // namespace clang 374 375 #endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 376