llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang @llvm/pr-subscribers-hlsl Author: Corentin Jabot (cor3ntin) <details> <summary>Changes</summary> In the standard, constraint satisfaction checking is done on the normalized form of a constraint. Clang instead substitutes on the non-normalized form, which causes us to report substitution failures in template arguments or concept ids, which is non-conforming but unavoidable without a parameter mapping This patch normalizes before satisfaction checking. However, we preserve concept-id nodes in the normalized form, solely for diagnostics purposes. This is a very incomplete attempt at addressing #<!-- -->61811 and related concepts related conformance bugs, ideally to make the implementation of concept template parameters easier There is still ~3 failing test files Fixes #<!-- -->135190 Fixes #<!-- -->61811 Co-authored-by: Younan Zhang <zyn7109@<!-- -->gmail.com> --- Patch is 258.38 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141776.diff 49 Files Affected: - (modified) clang/include/clang/AST/ASTConcept.h (+20-9) - (modified) clang/include/clang/AST/ASTContext.h (+43) - (modified) clang/include/clang/AST/TemplateBase.h (-1) - (modified) clang/include/clang/Sema/Sema.h (+43-41) - (modified) clang/include/clang/Sema/SemaConcept.h (+335-78) - (modified) clang/include/clang/Sema/Template.h (+22-6) - (modified) clang/lib/AST/ASTConcept.cpp (+23-4) - (modified) clang/lib/AST/ASTContext.cpp (+1-21) - (modified) clang/lib/AST/ASTImporter.cpp (+1-1) - (modified) clang/lib/Sema/SemaConcept.cpp (+1275-707) - (modified) clang/lib/Sema/SemaDeclCXX.cpp (+7-5) - (modified) clang/lib/Sema/SemaExprCXX.cpp (+10-6) - (modified) clang/lib/Sema/SemaOverload.cpp (+2-1) - (modified) clang/lib/Sema/SemaTemplate.cpp (+75-33) - (modified) clang/lib/Sema/SemaTemplateDeduction.cpp (+25-12) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+155-79) - (modified) clang/lib/Sema/TreeTransform.h (+15-10) - (modified) clang/lib/Serialization/ASTReaderDecl.cpp (+1-1) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+7-2) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+13-6) - (modified) clang/test/AST/ast-dump-concepts.cpp (+6-4) - (modified) clang/test/AST/ast-dump-ctad-alias.cpp (+11-10) - (modified) clang/test/CXX/drs/cwg25xx.cpp (+8-6) - (modified) clang/test/CXX/expr/expr.prim/expr.prim.id/p3.cpp (+2-1) - (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/compound-requirement.cpp (+7-7) - (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/nested-requirement.cpp (+15-20) - (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/simple-requirement.cpp (+2-2) - (modified) clang/test/CXX/expr/expr.prim/expr.prim.req/type-requirement.cpp (+6-6) - (modified) clang/test/CXX/temp/temp.constr/temp.constr.atomic/constrant-satisfaction-conversions.cpp (+2-3) - (modified) clang/test/CXX/temp/temp.constr/temp.constr.normal/p1.cpp (+42-17) - (modified) clang/test/CXX/temp/temp.param/p10-2a.cpp (+13-10) - (modified) clang/test/SemaCXX/cxx23-assume.cpp (+4-5) - (modified) clang/test/SemaCXX/cxx2b-deducing-this.cpp (+4-4) - (modified) clang/test/SemaCXX/cxx2c-fold-exprs.cpp (+162-40) - (modified) clang/test/SemaCXX/cxx2c-template-template-param.cpp (+2-2) - (modified) clang/test/SemaCXX/invalid-requirement-requires-expr.cpp (+3-4) - (modified) clang/test/SemaCXX/overload-resolution-deferred-templates.cpp (+1-2) - (modified) clang/test/SemaCXX/type-traits.cpp (+2-2) - (modified) clang/test/SemaHLSL/BuiltIns/Buffers.hlsl (+3-3) - (modified) clang/test/SemaHLSL/BuiltIns/RWBuffers.hlsl (+3-3) - (modified) clang/test/SemaTemplate/concepts-recovery-expr.cpp (+21-11) - (modified) clang/test/SemaTemplate/concepts-recursive-inst.cpp (+14-13) - (modified) clang/test/SemaTemplate/concepts.cpp (+11-3) - (modified) clang/test/SemaTemplate/deduction-guide.cpp (+9-6) - (modified) clang/test/SemaTemplate/instantiate-abbreviated-template.cpp (+1) - (modified) clang/test/SemaTemplate/instantiate-expanded-type-constraint.cpp (+2-2) - (modified) clang/test/SemaTemplate/instantiate-requires-expr.cpp (+15-5) - (modified) clang/test/SemaTemplate/instantiate-template-argument.cpp (+9-5) - (modified) clang/test/SemaTemplate/pr52970.cpp (+1-1) ``````````diff diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 72da0059744f2..9babfd39dd668 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -28,13 +28,23 @@ namespace clang { class ConceptDecl; class TemplateDecl; +class ConceptReference; class Expr; class NamedDecl; struct PrintingPolicy; +/// Pairs of unsatisfied atomic constraint expressions along with the +/// substituted constraint expr, if the template arguments could be +/// substituted into them, or a diagnostic if substitution resulted in +/// an invalid expression. +using UnsatisfiedConstraintRecord = + llvm::PointerUnion<const Expr *, const ConceptReference *, + std::pair<SourceLocation, StringRef> *>; + /// The result of a constraint satisfaction check, containing the necessary /// information to diagnose an unsatisfied constraint. class ConstraintSatisfaction : public llvm::FoldingSetNode { +private: // The template-like entity that 'owns' the constraint checked here (can be a // constrained entity or a concept). const NamedDecl *ConstraintOwner = nullptr; @@ -49,7 +59,6 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode { : ConstraintOwner(ConstraintOwner), TemplateArgs(TemplateArgs) {} using SubstitutionDiagnostic = std::pair<SourceLocation, StringRef>; - using Detail = llvm::PointerUnion<Expr *, SubstitutionDiagnostic *>; bool IsSatisfied = false; bool ContainsErrors = false; @@ -57,7 +66,7 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode { /// \brief The substituted constraint expr, if the template arguments could be /// substituted into them, or a diagnostic if substitution resulted in an /// invalid expression. - llvm::SmallVector<Detail, 4> Details; + llvm::SmallVector<UnsatisfiedConstraintRecord, 4> Details; void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) { Profile(ID, C, ConstraintOwner, TemplateArgs); @@ -75,13 +84,6 @@ class ConstraintSatisfaction : public llvm::FoldingSetNode { } }; -/// Pairs of unsatisfied atomic constraint expressions along with the -/// substituted constraint expr, if the template arguments could be -/// substituted into them, or a diagnostic if substitution resulted in -/// an invalid expression. -using UnsatisfiedConstraintRecord = - llvm::PointerUnion<Expr *, std::pair<SourceLocation, StringRef> *>; - /// \brief The result of a constraint satisfaction check, containing the /// necessary information to diagnose an unsatisfied constraint. /// @@ -101,6 +103,10 @@ struct ASTConstraintSatisfaction final : return getTrailingObjects() + NumRecords; } + ArrayRef<UnsatisfiedConstraintRecord> records() const { + return {begin(), end()}; + } + ASTConstraintSatisfaction(const ASTContext &C, const ConstraintSatisfaction &Satisfaction); ASTConstraintSatisfaction(const ASTContext &C, @@ -282,6 +288,11 @@ class TypeConstraint { } }; +/// Insertion operator for diagnostics. This allows sending TemplateName's +/// into a diagnostic with <<. +const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB, + const ConceptReference *C); + } // clang #endif // LLVM_CLANG_AST_ASTCONCEPT_H diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 1c17333b722f8..0f808cbe2c17c 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -51,6 +51,27 @@ class FixedPointSemantics; struct fltSemantics; template <typename T, unsigned N> class SmallPtrSet; +template <> struct DenseMapInfo<llvm::FoldingSetNodeID> { + static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; } + + static FoldingSetNodeID getTombstoneKey() { + FoldingSetNodeID id; + for (size_t i = 0; i < sizeof(id) / sizeof(unsigned); ++i) { + id.AddInteger(std::numeric_limits<unsigned>::max()); + } + return id; + } + + static unsigned getHashValue(const FoldingSetNodeID &Val) { + return Val.ComputeHash(); + } + + static bool isEqual(const FoldingSetNodeID &LHS, + const FoldingSetNodeID &RHS) { + return LHS == RHS; + } +}; + } // namespace llvm namespace clang { @@ -3852,4 +3873,26 @@ typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType return Value; } +template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> { + static FoldingSetNodeID getEmptyKey() { return FoldingSetNodeID{}; } + + static FoldingSetNodeID getTombstoneKey() { + FoldingSetNodeID id; + for (size_t i = 0; i < sizeof(id) / sizeof(unsigned); ++i) { + id.AddInteger(std::numeric_limits<unsigned>::max()); + } + return id; + } + + static unsigned getHashValue(const FoldingSetNodeID &Val) { + return Val.ComputeHash(); + } + + static bool isEqual(const FoldingSetNodeID &LHS, + const FoldingSetNodeID &RHS) { + return LHS == RHS; + } +}; + + #endif // LLVM_CLANG_AST_ASTCONTEXT_H diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index de248ac3cf703..0359f4beb6309 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -475,7 +475,6 @@ class TemplateArgument { /// Used to insert TemplateArguments into FoldingSets. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; }; - /// Location information for a TemplateArgument. struct TemplateArgumentLocInfo { struct TemplateTemplateArgLocInfo { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 88b67eed5fd37..a508d33018292 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -65,6 +65,7 @@ #include "clang/Sema/Redeclaration.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" +#include "clang/Sema/SemaConcept.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "llvm/ADT/APInt.h" @@ -11688,8 +11689,9 @@ class Sema final : public SemaBase { ExprResult CheckConceptTemplateId(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &ConceptNameInfo, - NamedDecl *FoundDecl, ConceptDecl *NamedConcept, - const TemplateArgumentListInfo *TemplateArgs); + NamedDecl *FoundDecl, TemplateDecl *NamedConcept, + const TemplateArgumentListInfo *TemplateArgs, + bool DoCheckConstraintSatisfaction = true); void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc); void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS, @@ -12002,6 +12004,13 @@ class Sema final : public SemaBase { bool UpdateArgsWithConversions = true, bool *ConstraintsNotSatisfied = nullptr); + bool CheckTemplateArgumentList( + TemplateDecl *Template, TemplateParameterList *Params, + SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, + const DefaultArguments &DefaultArgs, bool PartialTemplateArgs, + CheckTemplateArgumentInfo &CTAI, bool UpdateArgsWithConversions = true, + bool *ConstraintsNotSatisfied = nullptr); + bool CheckTemplateTypeArgument( TemplateTypeParmDecl *Param, TemplateArgumentLoc &Arg, SmallVectorImpl<TemplateArgument> &SugaredConverted, @@ -12776,6 +12785,9 @@ class Sema final : public SemaBase { void MarkUsedTemplateParameters(ArrayRef<TemplateArgument> TemplateArgs, unsigned Depth, llvm::SmallBitVector &Used); + void MarkUsedTemplateParameters(ArrayRef<TemplateArgumentLoc> TemplateArgs, + unsigned Depth, llvm::SmallBitVector &Used); + void MarkDeducedTemplateParameters(const FunctionTemplateDecl *FunctionTemplate, llvm::SmallBitVector &Deduced) { @@ -13073,6 +13085,8 @@ class Sema final : public SemaBase { /// Whether we're substituting into constraints. bool InConstraintSubstitution; + bool InParameterMappingSubstitution; + /// The point of instantiation or synthesis within the source code. SourceLocation PointOfInstantiation; @@ -13338,6 +13352,11 @@ class Sema final : public SemaBase { const MultiLevelTemplateArgumentList &TemplateArgs, TemplateArgumentListInfo &Outputs); + bool SubstTemplateArgumentsInParameterMapping( + ArrayRef<TemplateArgumentLoc> Args, SourceLocation BaseLoc, + const MultiLevelTemplateArgumentList &TemplateArgs, + TemplateArgumentListInfo &Out, bool BuildPackExpansionTypes); + /// Retrieve the template argument list(s) that should be used to /// instantiate the definition of the given declaration. /// @@ -13799,6 +13818,12 @@ class Sema final : public SemaBase { CodeSynthesisContexts.back().InConstraintSubstitution; } + bool inParameterMappingSubstitution() const { + return !CodeSynthesisContexts.empty() && + CodeSynthesisContexts.back().InParameterMappingSubstitution && + !inConstraintSubstitution(); + } + using EntityPrinter = llvm::function_ref<void(llvm::raw_ostream &)>; /// \brief create a Requirement::SubstitutionDiagnostic with only a @@ -14683,6 +14708,10 @@ class Sema final : public SemaBase { SatisfactionStack.swap(NewSS); } + using ConstrainedDeclOrNestedRequirement = + llvm::PointerUnion<const NamedDecl *, + const concepts::NestedRequirement *>; + /// Check whether the given expression is a valid constraint expression. /// A diagnostic is emitted if it is not, false is returned, and /// PossibleNonPrimary will be set to true if the failure might be due to a @@ -14707,44 +14736,12 @@ class Sema final : public SemaBase { /// \returns true if an error occurred and satisfaction could not be checked, /// false otherwise. bool CheckConstraintSatisfaction( - const NamedDecl *Template, + ConstrainedDeclOrNestedRequirement Entity, ArrayRef<AssociatedConstraint> AssociatedConstraints, const MultiLevelTemplateArgumentList &TemplateArgLists, - SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction) { - llvm::SmallVector<Expr *, 4> Converted; - return CheckConstraintSatisfaction(Template, AssociatedConstraints, - Converted, TemplateArgLists, - TemplateIDRange, Satisfaction); - } - - /// \brief Check whether the given list of constraint expressions are - /// satisfied (as if in a 'conjunction') given template arguments. - /// Additionally, takes an empty list of Expressions which is populated with - /// the instantiated versions of the ConstraintExprs. - /// \param Template the template-like entity that triggered the constraints - /// check (either a concept or a constrained entity). - /// \param ConstraintExprs a list of constraint expressions, treated as if - /// they were 'AND'ed together. - /// \param ConvertedConstraints a out parameter that will get populated with - /// the instantiated version of the ConstraintExprs if we successfully checked - /// satisfaction. - /// \param TemplateArgList the multi-level list of template arguments to - /// substitute into the constraint expression. This should be relative to the - /// top-level (hence multi-level), since we need to instantiate fully at the - /// time of checking. - /// \param TemplateIDRange The source range of the template id that - /// caused the constraints check. - /// \param Satisfaction if true is returned, will contain details of the - /// satisfaction, with enough information to diagnose an unsatisfied - /// expression. - /// \returns true if an error occurred and satisfaction could not be checked, - /// false otherwise. - bool CheckConstraintSatisfaction( - const NamedDecl *Template, - ArrayRef<AssociatedConstraint> AssociatedConstraints, - llvm::SmallVectorImpl<Expr *> &ConvertedConstraints, - const MultiLevelTemplateArgumentList &TemplateArgList, - SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction); + SourceRange TemplateIDRange, ConstraintSatisfaction &Satisfaction, + const ConceptReference *TopLevelConceptId = nullptr, + Expr **ConvertedExpr = nullptr); /// \brief Check whether the given non-dependent constraint expression is /// satisfied. Returns false and updates Satisfaction with the satisfaction @@ -14810,16 +14807,17 @@ class Sema final : public SemaBase { /// \param First whether this is the first time an unsatisfied constraint is /// diagnosed for this error. void DiagnoseUnsatisfiedConstraint(const ConstraintSatisfaction &Satisfaction, + SourceLocation Loc = {}, bool First = true); /// \brief Emit diagnostics explaining why a constraint expression was deemed /// unsatisfied. void - DiagnoseUnsatisfiedConstraint(const ASTConstraintSatisfaction &Satisfaction, + DiagnoseUnsatisfiedConstraint(const ConceptSpecializationExpr *ConstraintExpr, bool First = true); const NormalizedConstraint *getNormalizedAssociatedConstraints( - const NamedDecl *ConstrainedDecl, + ConstrainedDeclOrNestedRequirement Entity, ArrayRef<AssociatedConstraint> AssociatedConstraints); /// \brief Check whether the given declaration's associated constraints are @@ -14844,6 +14842,9 @@ class Sema final : public SemaBase { const NamedDecl *D1, ArrayRef<AssociatedConstraint> AC1, const NamedDecl *D2, ArrayRef<AssociatedConstraint> AC2); + llvm::DenseMap<llvm::FoldingSetNodeID, CachedConceptIdConstraint> + ConceptIdSatisfactionCache; + private: /// Caches pairs of template-like decls whose associated constraints were /// checked for subsumption and whether or not the first's constraints did in @@ -14854,7 +14855,8 @@ class Sema final : public SemaBase { /// constrained declarations). If an error occurred while normalizing the /// associated constraints of the template or concept, nullptr will be cached /// here. - llvm::DenseMap<const NamedDecl *, NormalizedConstraint *> NormalizationCache; + llvm::DenseMap<ConstrainedDeclOrNestedRequirement, NormalizedConstraint *> + NormalizationCache; llvm::ContextualFoldingSet<ConstraintSatisfaction, const ASTContext &> SatisfactionCache; diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index 648a9c51ae6c1..3ba48b75c1286 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -16,130 +16,387 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprConcepts.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/UnsignedOrNone.h" +#include "clang/Sema/Ownership.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/STLFunctionalExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Compiler.h" #include <optional> #include <utility> namespace clang { class Sema; +class MultiLevelTemplateArgumentList; -enum { ConstraintAlignment = 8 }; +/// \brief A normalized constraint, as defined in C++ [temp.constr.normal], is +/// either an atomic constraint, a conjunction of normalized constraints or a +/// disjunction of normalized constraints. + +struct NormalizedConstraint { + + enum class ConstraintKind { + Atomic = 0, + ConceptId, + FoldExpanded, + Compound, + }; + + enum CompoundConstraintKind { CCK_Conjunction, CCK_Disjunction }; + enum class FoldOperatorKind : unsigned int { And, Or }; + + using OccurenceList = llvm::SmallBitVector; + + friend bool + substituteParameterMappings(Sema &S, NormalizedConstraint &N, + const MultiLevelTemplateArgumentList &MLTAL, + const ASTTemplateArgumentListInfo *ArgsAsWritten, + TemplateParameterList *TemplateParams, + const NamedDecl *D); + +protected: + using ExprOrConcept = + llvm::PointerUnion<const Expr *, const ConceptReference *>; + + struct AtomicBits { + LLVM_PREFERRED_TYPE(ConstraintKind) + unsigned Kind : 5; + unsigned Placeholder : 1; + unsigned PackSubstitutionIndex : 26; + OccurenceList Indexes; + TemplateArgumentLoc *Args; + TemplateParameterList *ParamList; + ExprOrConcept ConstraintExpr; + const NamedDecl *ConstraintDecl; + }; + + struct FoldExpandedBits { + LLVM_PREFERRED_TYPE(ConstraintKind) + unsigned Kind : 5; + LLVM_PREFERRED_TYPE(FoldOperatorKind) + unsigned FoldOperator : 1; + unsigned Placeholder : 26; + OccurenceList Indexes; + TemplateArgumentLoc *Args; + TemplateParameterList *ParamList; + const Expr *Pattern; + const NamedDecl *ConstraintDecl; + NormalizedConstraint *Constraint; + }; + + struct ConceptIdBits : AtomicBits { + NormalizedConstraint *Sub; + + // Only used for parameter mapping. + const ConceptSpecializationExpr *CSE; + }; + + struct CompoundBits { + LLVM_PREFERRED_TYPE(ConstraintKind) + unsigned Kind : 5; + LLVM_PREFERRED_TYPE(CompoundConstraintKind) + unsigned CCK : 1; + NormalizedConstraint *LHS; + NormalizedConstraint *RHS; + }; + + union { + AtomicBits Atomic; + FoldExpandedBits FoldExpanded; + ConceptIdBits ConceptId; + CompoundBits Compound; + }; + + ~NormalizedConstraint() { + if (getKind() != ConstraintKind::Compound) + Atomic.Indexes.llvm::SmallBitVector::~SmallBitVector(); + } + + NormalizedConstraint(const Expr *ConstraintExpr, + const NamedDecl *ConstraintDecl, + UnsignedOrNone PackIndex) + : Atomic{llvm::to_underlying(ConstraintKind::Atomic), + /*Placeholder=*/0, + PackIndex.toInternalRepresentation(), + /*Indexes=*/{}, + /*Args=*/nullptr, + /*ParamList=*/nullptr, + ConstraintExpr, + ConstraintDecl} {} + + NormalizedConstraint(const Expr *Pattern, FoldOperatorKind OpKind, + NormalizedConstraint *Constraint, + const NamedDecl *ConstraintDecl) + : FoldExpanded{llvm::to_underlying(ConstraintKind::FoldExpanded), + llvm::to_underlying(OpKind), + /*Placeholder=*/0, + /*Indexes=*/{}, + /*Args=*/nullptr, + /*ParamList=*/nullptr, + Pattern, + ConstraintDecl, + Constraint} {} + + NormalizedConstraint(const ConceptReference *ConceptId, + const NamedDecl *ConstraintDecl, + NormalizedConstraint *SubConstraint, + const ConceptSpecializationExpr *CSE, + UnsignedOrNone PackIndex) + : ConceptId{{llvm::to_underlying(ConstraintKind::ConceptId), + /*Placeholder=*/0, PackIndex.toInternalRepresentation(), + /*Indexes=*/{}, + /*Args=*/nullptr, /*ParamList=*/nullptr, ConceptId, + ConstraintDecl}, + SubConstraint, + CSE} {} + + NormalizedConstraint(NormalizedConstraint *LHS, CompoundConstraintKind CCK, + NormalizedConstraint *RHS) + : Compound{llvm::to_underlying(ConstraintKind::Compound), CCK, LHS, RHS} { + } -struct alignas(ConstraintAlignment) AtomicConstraint { - const Expr *ConstraintExpr; - const NamedDecl *ConstraintDecl; - std::optional<ArrayRef<TemplateArgumentLoc>> ParameterMapping; + bool hasParameterMapping() const { + return getKind() != ConstraintKind::Compound + && Atomic.Args != nullptr; + } + + const OccurenceList &mappingOccurenceList() const { + assert(hasParameterMapping() && "Th... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/141776 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
