Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:05

0001 //===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file provides types used with Sema's template argument deduction
0010 // routines.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
0015 #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H
0016 
0017 #include "clang/Sema/Ownership.h"
0018 #include "clang/Sema/SemaConcept.h"
0019 #include "clang/AST/ASTConcept.h"
0020 #include "clang/AST/DeclAccessPair.h"
0021 #include "clang/AST/DeclTemplate.h"
0022 #include "clang/AST/TemplateBase.h"
0023 #include "clang/Basic/PartialDiagnostic.h"
0024 #include "clang/Basic/SourceLocation.h"
0025 #include "llvm/ADT/SmallVector.h"
0026 #include <cassert>
0027 #include <cstddef>
0028 #include <optional>
0029 #include <utility>
0030 
0031 namespace clang {
0032 
0033 class Decl;
0034 struct DeducedPack;
0035 class Sema;
0036 enum class TemplateDeductionResult;
0037 
0038 namespace sema {
0039 
0040 /// Provides information about an attempted template argument
0041 /// deduction, whose success or failure was described by a
0042 /// TemplateDeductionResult value.
0043 class TemplateDeductionInfo {
0044   /// The deduced template argument list.
0045   TemplateArgumentList *DeducedSugared = nullptr, *DeducedCanonical = nullptr;
0046 
0047   /// The source location at which template argument
0048   /// deduction is occurring.
0049   SourceLocation Loc;
0050 
0051   /// Have we suppressed an error during deduction?
0052   bool HasSFINAEDiagnostic = false;
0053 
0054   /// Have we matched any packs on the parameter side, versus any non-packs on
0055   /// the argument side, in a context where the opposite matching is also
0056   /// allowed?
0057   bool MatchedPackOnParmToNonPackOnArg = false;
0058 
0059   /// The template parameter depth for which we're performing deduction.
0060   unsigned DeducedDepth;
0061 
0062   /// The number of parameters with explicitly-specified template arguments,
0063   /// up to and including the partially-specified pack (if any).
0064   unsigned ExplicitArgs = 0;
0065 
0066   /// Warnings (and follow-on notes) that were suppressed due to
0067   /// SFINAE while performing template argument deduction.
0068   SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics;
0069 
0070 public:
0071   TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0)
0072       : Loc(Loc), DeducedDepth(DeducedDepth) {}
0073   TemplateDeductionInfo(const TemplateDeductionInfo &) = delete;
0074   TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete;
0075 
0076   enum ForBaseTag { ForBase };
0077   /// Create temporary template deduction info for speculatively deducing
0078   /// against a base class of an argument's type.
0079   TemplateDeductionInfo(ForBaseTag, const TemplateDeductionInfo &Info)
0080       : DeducedSugared(Info.DeducedSugared), Loc(Info.Loc),
0081         DeducedDepth(Info.DeducedDepth), ExplicitArgs(Info.ExplicitArgs) {}
0082 
0083   /// Returns the location at which template argument is
0084   /// occurring.
0085   SourceLocation getLocation() const {
0086     return Loc;
0087   }
0088 
0089   /// The depth of template parameters for which deduction is being
0090   /// performed.
0091   unsigned getDeducedDepth() const {
0092     return DeducedDepth;
0093   }
0094 
0095   bool hasMatchedPackOnParmToNonPackOnArg() const {
0096     return MatchedPackOnParmToNonPackOnArg;
0097   }
0098 
0099   void setMatchedPackOnParmToNonPackOnArg() {
0100     MatchedPackOnParmToNonPackOnArg = true;
0101   }
0102 
0103   /// Get the number of explicitly-specified arguments.
0104   unsigned getNumExplicitArgs() const {
0105     return ExplicitArgs;
0106   }
0107 
0108   /// Take ownership of the deduced template argument lists.
0109   TemplateArgumentList *takeSugared() {
0110     TemplateArgumentList *Result = DeducedSugared;
0111     DeducedSugared = nullptr;
0112     return Result;
0113   }
0114   TemplateArgumentList *takeCanonical() {
0115     TemplateArgumentList *Result = DeducedCanonical;
0116     DeducedCanonical = nullptr;
0117     return Result;
0118   }
0119 
0120   /// Take ownership of the SFINAE diagnostic.
0121   void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) {
0122     assert(HasSFINAEDiagnostic);
0123     PD.first = SuppressedDiagnostics.front().first;
0124     PD.second.swap(SuppressedDiagnostics.front().second);
0125     clearSFINAEDiagnostic();
0126   }
0127 
0128   /// Discard any SFINAE diagnostics.
0129   void clearSFINAEDiagnostic() {
0130     SuppressedDiagnostics.clear();
0131     HasSFINAEDiagnostic = false;
0132   }
0133 
0134   /// Peek at the SFINAE diagnostic.
0135   const PartialDiagnosticAt &peekSFINAEDiagnostic() const {
0136     assert(HasSFINAEDiagnostic);
0137     return SuppressedDiagnostics.front();
0138   }
0139 
0140   /// Provide an initial template argument list that contains the
0141   /// explicitly-specified arguments.
0142   void setExplicitArgs(TemplateArgumentList *NewDeducedSugared,
0143                        TemplateArgumentList *NewDeducedCanonical) {
0144     assert(NewDeducedSugared->size() == NewDeducedCanonical->size());
0145     DeducedSugared = NewDeducedSugared;
0146     DeducedCanonical = NewDeducedCanonical;
0147     ExplicitArgs = DeducedSugared->size();
0148   }
0149 
0150   /// Provide a new template argument list that contains the
0151   /// results of template argument deduction.
0152   void reset(TemplateArgumentList *NewDeducedSugared,
0153              TemplateArgumentList *NewDeducedCanonical) {
0154     DeducedSugared = NewDeducedSugared;
0155     DeducedCanonical = NewDeducedCanonical;
0156   }
0157 
0158   /// Is a SFINAE diagnostic available?
0159   bool hasSFINAEDiagnostic() const {
0160     return HasSFINAEDiagnostic;
0161   }
0162 
0163   /// Set the diagnostic which caused the SFINAE failure.
0164   void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) {
0165     // Only collect the first diagnostic.
0166     if (HasSFINAEDiagnostic)
0167       return;
0168     SuppressedDiagnostics.clear();
0169     SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
0170     HasSFINAEDiagnostic = true;
0171   }
0172 
0173   /// Add a new diagnostic to the set of diagnostics
0174   void addSuppressedDiagnostic(SourceLocation Loc,
0175                                PartialDiagnostic PD) {
0176     if (HasSFINAEDiagnostic)
0177       return;
0178     SuppressedDiagnostics.emplace_back(Loc, std::move(PD));
0179   }
0180 
0181   /// Iterator over the set of suppressed diagnostics.
0182   using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator;
0183 
0184   /// Returns an iterator at the beginning of the sequence of suppressed
0185   /// diagnostics.
0186   diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); }
0187 
0188   /// Returns an iterator at the end of the sequence of suppressed
0189   /// diagnostics.
0190   diag_iterator diag_end() const { return SuppressedDiagnostics.end(); }
0191 
0192   /// The template parameter to which a template argument
0193   /// deduction failure refers.
0194   ///
0195   /// Depending on the result of template argument deduction, this
0196   /// template parameter may have different meanings:
0197   ///
0198   ///   TDK_Incomplete: this is the first template parameter whose
0199   ///   corresponding template argument was not deduced.
0200   ///
0201   ///   TDK_IncompletePack: this is the expanded parameter pack for
0202   ///   which we deduced too few arguments.
0203   ///
0204   ///   TDK_Inconsistent: this is the template parameter for which
0205   ///   two different template argument values were deduced.
0206   TemplateParameter Param;
0207 
0208   /// The first template argument to which the template
0209   /// argument deduction failure refers.
0210   ///
0211   /// Depending on the result of the template argument deduction,
0212   /// this template argument may have different meanings:
0213   ///
0214   ///   TDK_IncompletePack: this is the number of arguments we deduced
0215   ///   for the pack.
0216   ///
0217   ///   TDK_Inconsistent: this argument is the first value deduced
0218   ///   for the corresponding template parameter.
0219   ///
0220   ///   TDK_SubstitutionFailure: this argument is the template
0221   ///   argument we were instantiating when we encountered an error.
0222   ///
0223   ///   TDK_DeducedMismatch: this is the parameter type, after substituting
0224   ///   deduced arguments.
0225   ///
0226   ///   TDK_NonDeducedMismatch: this is the component of the 'parameter'
0227   ///   of the deduction, directly provided in the source code.
0228   TemplateArgument FirstArg;
0229 
0230   /// The second template argument to which the template
0231   /// argument deduction failure refers.
0232   ///
0233   ///   TDK_Inconsistent: this argument is the second value deduced
0234   ///   for the corresponding template parameter.
0235   ///
0236   ///   TDK_DeducedMismatch: this is the (adjusted) call argument type.
0237   ///
0238   ///   TDK_NonDeducedMismatch: this is the mismatching component of the
0239   ///   'argument' of the deduction, from which we are deducing arguments.
0240   ///
0241   /// FIXME: Finish documenting this.
0242   TemplateArgument SecondArg;
0243 
0244   /// The index of the function argument that caused a deduction
0245   /// failure.
0246   ///
0247   ///   TDK_DeducedMismatch: this is the index of the argument that had a
0248   ///   different argument type from its substituted parameter type.
0249   unsigned CallArgIndex = 0;
0250 
0251   // C++20 [over.match.class.deduct]p5.2:
0252   //   During template argument deduction for the aggregate deduction
0253   //   candidate, the number of elements in a trailing parameter pack is only
0254   //   deduced from the number of remaining function arguments if it is not
0255   //   otherwise deduced.
0256   bool AggregateDeductionCandidateHasMismatchedArity = false;
0257 
0258   /// Information on packs that we're currently expanding.
0259   ///
0260   /// FIXME: This should be kept internal to SemaTemplateDeduction.
0261   SmallVector<DeducedPack *, 8> PendingDeducedPacks;
0262 
0263   /// \brief The constraint satisfaction details resulting from the associated
0264   /// constraints satisfaction tests.
0265   ConstraintSatisfaction AssociatedConstraintsSatisfaction;
0266 };
0267 
0268 } // namespace sema
0269 
0270 /// A structure used to record information about a failed
0271 /// template argument deduction, for diagnosis.
0272 struct DeductionFailureInfo {
0273   /// A Sema::TemplateDeductionResult.
0274   unsigned Result : 8;
0275 
0276   /// Indicates whether a diagnostic is stored in Diagnostic.
0277   unsigned HasDiagnostic : 1;
0278 
0279   /// Opaque pointer containing additional data about
0280   /// this deduction failure.
0281   void *Data;
0282 
0283   /// A diagnostic indicating why deduction failed.
0284   alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)];
0285 
0286   /// Retrieve the diagnostic which caused this deduction failure,
0287   /// if any.
0288   PartialDiagnosticAt *getSFINAEDiagnostic();
0289 
0290   /// Retrieve the template parameter this deduction failure
0291   /// refers to, if any.
0292   TemplateParameter getTemplateParameter();
0293 
0294   /// Retrieve the template argument list associated with this
0295   /// deduction failure, if any.
0296   TemplateArgumentList *getTemplateArgumentList();
0297 
0298   /// Return the first template argument this deduction failure
0299   /// refers to, if any.
0300   const TemplateArgument *getFirstArg();
0301 
0302   /// Return the second template argument this deduction failure
0303   /// refers to, if any.
0304   const TemplateArgument *getSecondArg();
0305 
0306   /// Return the index of the call argument that this deduction
0307   /// failure refers to, if any.
0308   std::optional<unsigned> getCallArgIndex();
0309 
0310   /// Free any memory associated with this deduction failure.
0311   void Destroy();
0312 
0313   TemplateDeductionResult getResult() const {
0314     return static_cast<TemplateDeductionResult>(Result);
0315   }
0316 };
0317 
0318 /// TemplateSpecCandidate - This is a generalization of OverloadCandidate
0319 /// which keeps track of template argument deduction failure info, when
0320 /// handling explicit specializations (and instantiations) of templates
0321 /// beyond function overloading.
0322 /// For now, assume that the candidates are non-matching specializations.
0323 /// TODO: In the future, we may need to unify/generalize this with
0324 /// OverloadCandidate.
0325 struct TemplateSpecCandidate {
0326   /// The declaration that was looked up, together with its access.
0327   /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
0328   DeclAccessPair FoundDecl;
0329 
0330   /// Specialization - The actual specialization that this candidate
0331   /// represents. When NULL, this may be a built-in candidate.
0332   Decl *Specialization;
0333 
0334   /// Template argument deduction info
0335   DeductionFailureInfo DeductionFailure;
0336 
0337   void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) {
0338     FoundDecl = Found;
0339     Specialization = Spec;
0340     DeductionFailure = Info;
0341   }
0342 
0343   /// Diagnose a template argument deduction failure.
0344   void NoteDeductionFailure(Sema &S, bool ForTakingAddress);
0345 };
0346 
0347 /// TemplateSpecCandidateSet - A set of generalized overload candidates,
0348 /// used in template specializations.
0349 /// TODO: In the future, we may need to unify/generalize this with
0350 /// OverloadCandidateSet.
0351 class TemplateSpecCandidateSet {
0352   SmallVector<TemplateSpecCandidate, 16> Candidates;
0353   SourceLocation Loc;
0354 
0355   // Stores whether we're taking the address of these candidates. This helps us
0356   // produce better error messages when dealing with the pass_object_size
0357   // attribute on parameters.
0358   bool ForTakingAddress;
0359 
0360   void destroyCandidates();
0361 
0362 public:
0363   TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false)
0364       : Loc(Loc), ForTakingAddress(ForTakingAddress) {}
0365   TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete;
0366   TemplateSpecCandidateSet &
0367   operator=(const TemplateSpecCandidateSet &) = delete;
0368   ~TemplateSpecCandidateSet() { destroyCandidates(); }
0369 
0370   SourceLocation getLocation() const { return Loc; }
0371 
0372   /// Clear out all of the candidates.
0373   /// TODO: This may be unnecessary.
0374   void clear();
0375 
0376   using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator;
0377 
0378   iterator begin() { return Candidates.begin(); }
0379   iterator end() { return Candidates.end(); }
0380 
0381   size_t size() const { return Candidates.size(); }
0382   bool empty() const { return Candidates.empty(); }
0383 
0384   /// Add a new candidate with NumConversions conversion sequence slots
0385   /// to the overload set.
0386   TemplateSpecCandidate &addCandidate() {
0387     Candidates.emplace_back();
0388     return Candidates.back();
0389   }
0390 
0391   void NoteCandidates(Sema &S, SourceLocation Loc);
0392 
0393   void NoteCandidates(Sema &S, SourceLocation Loc) const {
0394     const_cast<TemplateSpecCandidateSet *>(this)->NoteCandidates(S, Loc);
0395   }
0396 };
0397 
0398 } // namespace clang
0399 
0400 #endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H