- //===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file provides types used with Sema's template argument deduction 
- // routines. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 
- #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 
-   
- #include "clang/Sema/Ownership.h" 
- #include "clang/Sema/SemaConcept.h" 
- #include "clang/AST/ASTConcept.h" 
- #include "clang/AST/DeclAccessPair.h" 
- #include "clang/AST/DeclTemplate.h" 
- #include "clang/AST/TemplateBase.h" 
- #include "clang/Basic/PartialDiagnostic.h" 
- #include "clang/Basic/SourceLocation.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include <cassert> 
- #include <cstddef> 
- #include <optional> 
- #include <utility> 
-   
- namespace clang { 
-   
- class Decl; 
- struct DeducedPack; 
- class Sema; 
-   
- namespace sema { 
-   
- /// Provides information about an attempted template argument 
- /// deduction, whose success or failure was described by a 
- /// TemplateDeductionResult value. 
- class TemplateDeductionInfo { 
-   /// The deduced template argument list. 
-   TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr; 
-   
-   /// The source location at which template argument 
-   /// deduction is occurring. 
-   SourceLocation Loc; 
-   
-   /// Have we suppressed an error during deduction? 
-   bool HasSFINAEDiagnostic = false; 
-   
-   /// The template parameter depth for which we're performing deduction. 
-   unsigned DeducedDepth; 
-   
-   /// The number of parameters with explicitly-specified template arguments, 
-   /// up to and including the partially-specified pack (if any). 
-   unsigned ExplicitArgs = 0; 
-   
-   /// Warnings (and follow-on notes) that were suppressed due to 
-   /// SFINAE while performing template argument deduction. 
-   SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; 
-   
- public: 
-   TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0) 
-       : Loc(Loc), DeducedDepth(DeducedDepth) {} 
-   TemplateDeductionInfo(const TemplateDeductionInfo &) = delete; 
-   TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete; 
-   
-   enum ForBaseTag { ForBase }; 
-   /// Create temporary template deduction info for speculatively deducing 
-   /// against a base class of an argument's type. 
-   TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info) 
-       : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc), 
-         DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {} 
-   
-   /// Returns the location at which template argument is 
-   /// occurring. 
-   SourceLocation getLocation() const { 
-     return Loc; 
-   } 
-   
-   /// The depth of template parameters for which deduction is being 
-   /// performed. 
-   unsigned getDeducedDepth() const { 
-     return DeducedDepth; 
-   } 
-   
-   /// Get the number of explicitly-specified arguments. 
-   unsigned getNumExplicitArgs() const { 
-     return ExplicitArgs; 
-   } 
-   
-   /// Take ownership of the deduced template argument lists. 
-   TemplateArgumentList *takeSugared() { 
-     TemplateArgumentList *Result = DeducedSugared; 
-     DeducedSugared = nullptr; 
-     return Result; 
-   } 
-   TemplateArgumentList *takeCanonical() { 
-     TemplateArgumentList *Result = DeducedCanonical; 
-     DeducedCanonical = nullptr; 
-     return Result; 
-   } 
-   
-   /// Take ownership of the SFINAE diagnostic. 
-   void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) { 
-     assert(HasSFINAEDiagnostic); 
-     PD.first = SuppressedDiagnostics.front().first; 
-     PD.second.swap(SuppressedDiagnostics.front().second); 
-     clearSFINAEDiagnostic(); 
-   } 
-   
-   /// Discard any SFINAE diagnostics. 
-   void clearSFINAEDiagnostic() { 
-     SuppressedDiagnostics.clear(); 
-     HasSFINAEDiagnostic = false; 
-   } 
-   
-   /// Peek at the SFINAE diagnostic. 
-   const PartialDiagnosticAt &peekSFINAEDiagnostic() const { 
-     assert(HasSFINAEDiagnostic); 
-     return SuppressedDiagnostics.front(); 
-   } 
-   
-   /// Provide an initial template argument list that contains the 
-   /// explicitly-specified arguments. 
-   void setExplicitArgs(TemplateArgumentList *NewDeducedSugared, 
-                        TemplateArgumentList *NewDeducedCanonical) { 
-     assert(NewDeducedSugared->size() == NewDeducedCanonical->size()); 
-     DeducedSugared = NewDeducedSugared; 
-     DeducedCanonical = NewDeducedCanonical; 
-     ExplicitArgs = DeducedSugared->size(); 
-   } 
-   
-   /// Provide a new template argument list that contains the 
-   /// results of template argument deduction. 
-   void reset(TemplateArgumentList *NewDeducedSugared, 
-              TemplateArgumentList *NewDeducedCanonical) { 
-     DeducedSugared = NewDeducedSugared; 
-     DeducedCanonical = NewDeducedCanonical; 
-   } 
-   
-   /// Is a SFINAE diagnostic available? 
-   bool hasSFINAEDiagnostic() const { 
-     return HasSFINAEDiagnostic; 
-   } 
-   
-   /// Set the diagnostic which caused the SFINAE failure. 
-   void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { 
-     // Only collect the first diagnostic. 
-     if (HasSFINAEDiagnostic) 
-       return; 
-     SuppressedDiagnostics.clear(); 
-     SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); 
-     HasSFINAEDiagnostic = true; 
-   } 
-   
-   /// Add a new diagnostic to the set of diagnostics 
-   void addSuppressedDiagnostic(SourceLocation Loc, 
-                                PartialDiagnostic PD) { 
-     if (HasSFINAEDiagnostic) 
-       return; 
-     SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); 
-   } 
-   
-   /// Iterator over the set of suppressed diagnostics. 
-   using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator; 
-   
-   /// Returns an iterator at the beginning of the sequence of suppressed 
-   /// diagnostics. 
-   diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); } 
-   
-   /// Returns an iterator at the end of the sequence of suppressed 
-   /// diagnostics. 
-   diag_iterator diag_end() const { return SuppressedDiagnostics.end(); } 
-   
-   /// The template parameter to which a template argument 
-   /// deduction failure refers. 
-   /// 
-   /// Depending on the result of template argument deduction, this 
-   /// template parameter may have different meanings: 
-   /// 
-   ///   TDK_Incomplete: this is the first template parameter whose 
-   ///   corresponding template argument was not deduced. 
-   /// 
-   ///   TDK_IncompletePack: this is the expanded parameter pack for 
-   ///   which we deduced too few arguments. 
-   /// 
-   ///   TDK_Inconsistent: this is the template parameter for which 
-   ///   two different template argument values were deduced. 
-   TemplateParameter Param; 
-   
-   /// The first template argument to which the template 
-   /// argument deduction failure refers. 
-   /// 
-   /// Depending on the result of the template argument deduction, 
-   /// this template argument may have different meanings: 
-   /// 
-   ///   TDK_IncompletePack: this is the number of arguments we deduced 
-   ///   for the pack. 
-   /// 
-   ///   TDK_Inconsistent: this argument is the first value deduced 
-   ///   for the corresponding template parameter. 
-   /// 
-   ///   TDK_SubstitutionFailure: this argument is the template 
-   ///   argument we were instantiating when we encountered an error. 
-   /// 
-   ///   TDK_DeducedMismatch: this is the parameter type, after substituting 
-   ///   deduced arguments. 
-   /// 
-   ///   TDK_NonDeducedMismatch: this is the component of the 'parameter' 
-   ///   of the deduction, directly provided in the source code. 
-   TemplateArgument FirstArg; 
-   
-   /// The second template argument to which the template 
-   /// argument deduction failure refers. 
-   /// 
-   ///   TDK_Inconsistent: this argument is the second value deduced 
-   ///   for the corresponding template parameter. 
-   /// 
-   ///   TDK_DeducedMismatch: this is the (adjusted) call argument type. 
-   /// 
-   ///   TDK_NonDeducedMismatch: this is the mismatching component of the 
-   ///   'argument' of the deduction, from which we are deducing arguments. 
-   /// 
-   /// FIXME: Finish documenting this. 
-   TemplateArgument SecondArg; 
-   
-   /// The index of the function argument that caused a deduction 
-   /// failure. 
-   /// 
-   ///   TDK_DeducedMismatch: this is the index of the argument that had a 
-   ///   different argument type from its substituted parameter type. 
-   unsigned CallArgIndex = 0; 
-   
-   /// Information on packs that we're currently expanding. 
-   /// 
-   /// FIXME: This should be kept internal to SemaTemplateDeduction. 
-   SmallVector<DeducedPack *, 8> PendingDeducedPacks; 
-   
-   /// \brief The constraint satisfaction details resulting from the associated 
-   /// constraints satisfaction tests. 
-   ConstraintSatisfaction AssociatedConstraintsSatisfaction; 
- }; 
-   
- } // namespace sema 
-   
- /// A structure used to record information about a failed 
- /// template argument deduction, for diagnosis. 
- struct DeductionFailureInfo { 
-   /// A Sema::TemplateDeductionResult. 
-   unsigned Result : 8; 
-   
-   /// Indicates whether a diagnostic is stored in Diagnostic. 
-   unsigned HasDiagnostic : 1; 
-   
-   /// Opaque pointer containing additional data about 
-   /// this deduction failure. 
-   void *Data; 
-   
-   /// A diagnostic indicating why deduction failed. 
-   alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)]; 
-   
-   /// Retrieve the diagnostic which caused this deduction failure, 
-   /// if any. 
-   PartialDiagnosticAt *getSFINAEDiagnostic(); 
-   
-   /// Retrieve the template parameter this deduction failure 
-   /// refers to, if any. 
-   TemplateParameter getTemplateParameter(); 
-   
-   /// Retrieve the template argument list associated with this 
-   /// deduction failure, if any. 
-   TemplateArgumentList *getTemplateArgumentList(); 
-   
-   /// Return the first template argument this deduction failure 
-   /// refers to, if any. 
-   const TemplateArgument *getFirstArg(); 
-   
-   /// Return the second template argument this deduction failure 
-   /// refers to, if any. 
-   const TemplateArgument *getSecondArg(); 
-   
-   /// Return the index of the call argument that this deduction 
-   /// failure refers to, if any. 
-   std::optional<unsigned> getCallArgIndex(); 
-   
-   /// Free any memory associated with this deduction failure. 
-   void Destroy(); 
- }; 
-   
- /// TemplateSpecCandidate - This is a generalization of OverloadCandidate 
- /// which keeps track of template argument deduction failure info, when 
- /// handling explicit specializations (and instantiations) of templates 
- /// beyond function overloading. 
- /// For now, assume that the candidates are non-matching specializations. 
- /// TODO: In the future, we may need to unify/generalize this with 
- /// OverloadCandidate. 
- struct TemplateSpecCandidate { 
-   /// The declaration that was looked up, together with its access. 
-   /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl. 
-   DeclAccessPair FoundDecl; 
-   
-   /// Specialization - The actual specialization that this candidate 
-   /// represents. When NULL, this may be a built-in candidate. 
-   Decl *Specialization; 
-   
-   /// Template argument deduction info 
-   DeductionFailureInfo DeductionFailure; 
-   
-   void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) { 
-     FoundDecl = Found; 
-     Specialization = Spec; 
-     DeductionFailure = Info; 
-   } 
-   
-   /// Diagnose a template argument deduction failure. 
-   void NoteDeductionFailure(Sema &S, bool ForTakingAddress); 
- }; 
-   
- /// TemplateSpecCandidateSet - A set of generalized overload candidates, 
- /// used in template specializations. 
- /// TODO: In the future, we may need to unify/generalize this with 
- /// OverloadCandidateSet. 
- class TemplateSpecCandidateSet { 
-   SmallVector<TemplateSpecCandidate, 16> Candidates; 
-   SourceLocation Loc; 
-   
-   // Stores whether we're taking the address of these candidates. This helps us 
-   // produce better error messages when dealing with the pass_object_size 
-   // attribute on parameters. 
-   bool ForTakingAddress; 
-   
-   void destroyCandidates(); 
-   
- public: 
-   TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false) 
-       : Loc(Loc), ForTakingAddress(ForTakingAddress) {} 
-   TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete; 
-   TemplateSpecCandidateSet & 
-   operator=(const TemplateSpecCandidateSet &) = delete; 
-   ~TemplateSpecCandidateSet() { destroyCandidates(); } 
-   
-   SourceLocation getLocation() const { return Loc; } 
-   
-   /// Clear out all of the candidates. 
-   /// TODO: This may be unnecessary. 
-   void clear(); 
-   
-   using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator; 
-   
-   iterator begin() { return Candidates.begin(); } 
-   iterator end() { return Candidates.end(); } 
-   
-   size_t size() const { return Candidates.size(); } 
-   bool empty() const { return Candidates.empty(); } 
-   
-   /// Add a new candidate with NumConversions conversion sequence slots 
-   /// to the overload set. 
-   TemplateSpecCandidate &addCandidate() { 
-     Candidates.emplace_back(); 
-     return Candidates.back(); 
-   } 
-   
-   void NoteCandidates(Sema &S, SourceLocation Loc); 
-   
-   void NoteCandidates(Sema &S, SourceLocation Loc) const { 
-     const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc); 
-   } 
- }; 
-   
- } // namespace clang 
-   
- #endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H 
-