================ @@ -143,13 +148,116 @@ struct NormalizedConstraint { return Constraint.get<AtomicConstraint *>(); } + FoldExpandedConstraint *getFoldExpandedConstraint() const { + assert(isFoldExpanded() && + "getFoldExpandedConstraint called on non-fold-expanded constraint."); + return Constraint.get<FoldExpandedConstraint *>(); + } + private: static std::optional<NormalizedConstraint> fromConstraintExprs(Sema &S, NamedDecl *D, ArrayRef<const Expr *> E); static std::optional<NormalizedConstraint> fromConstraintExpr(Sema &S, NamedDecl *D, const Expr *E); }; +struct FoldExpandedConstraint { + enum class FoldOperatorKind { FoAnd, FoOr } Kind; + NormalizedConstraint Constraint; + const Expr *Pattern; + + FoldExpandedConstraint(FoldOperatorKind K, NormalizedConstraint C, + const Expr *Pattern) + : Kind(K), Constraint(std::move(C)), Pattern(Pattern) {}; + + template <typename AtomicSubsumptionEvaluator> + bool subsumes(const FoldExpandedConstraint &Other, + AtomicSubsumptionEvaluator E) const; + + static bool AreSubsumptionElligible(const FoldExpandedConstraint &A, + const FoldExpandedConstraint &B); +}; + +const NormalizedConstraint *getNormalizedAssociatedConstraints( + Sema &S, NamedDecl *ConstrainedDecl, + ArrayRef<const Expr *> AssociatedConstraints); + +template <typename AtomicSubsumptionEvaluator> +bool subsumes(const NormalForm &PDNF, const NormalForm &QCNF, + AtomicSubsumptionEvaluator E) { + // C++ [temp.constr.order] p2 + // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the + // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in + // the conjuctive normal form of Q, where [...] + for (const auto &Pi : PDNF) { + for (const auto &Qj : QCNF) { + // C++ [temp.constr.order] p2 + // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if + // and only if there exists an atomic constraint Pia in Pi for which + // there exists an atomic constraint, Qjb, in Qj such that Pia + // subsumes Qjb. + bool Found = false; + for (NormalFormConstraint Pia : Pi) { + for (NormalFormConstraint Qjb : Qj) { + if (Pia.is<FoldExpandedConstraint *>() && + Qjb.is<FoldExpandedConstraint *>()) { + if (Pia.get<FoldExpandedConstraint *>()->subsumes( + *Qjb.get<FoldExpandedConstraint *>(), E)) { + Found = true; + break; + } + } else if (Pia.is<AtomicConstraint *>() && + Qjb.is<AtomicConstraint *>()) { + if (E(*Pia.get<AtomicConstraint *>(), + *Qjb.get<AtomicConstraint *>())) { + Found = true; + break; + } + } + } + if (Found) + break; + } + if (!Found) + return false; + } + } + return true; +} + +template <typename AtomicSubsumptionEvaluator> +bool subsumes(Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, NamedDecl *DQ, ---------------- AaronBallman wrote:
Errr the return type here worries me because it's easy to assume this returns `true` on subsumption rather than looking at `Subsumes` for that. WDYT? https://github.com/llvm/llvm-project/pull/98160 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits