123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|