[clang] [Clang][C++26] Implement "Ordering of constraints involving fold expressions (PR #98160)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 10 06:15:09 PDT 2024
================
@@ -143,13 +157,125 @@ 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 { And, Or } 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,
+ const AtomicSubsumptionEvaluator &E) const;
+
+ static bool AreCompatibleForSubsumption(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,
+ const 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,
+ ArrayRef<const Expr *> Q, bool &Subsumes,
+ const AtomicSubsumptionEvaluator &E) {
+ // C++ [temp.constr.order] p2
+ // In order to determine if a constraint P subsumes a constraint Q, P is
+ // transformed into disjunctive normal form, and Q is transformed into
+ // conjunctive normal form. [...]
+ const NormalizedConstraint *PNormalized =
+ getNormalizedAssociatedConstraints(S, DP, P);
+ if (!PNormalized)
+ return true;
+ NormalForm PDNF = makeDNF(*PNormalized);
+
+ const NormalizedConstraint *QNormalized =
+ getNormalizedAssociatedConstraints(S, DQ, Q);
+ if (!QNormalized)
+ return true;
+ NormalForm QCNF = makeCNF(*QNormalized);
+
+ Subsumes = subsumes(PDNF, QCNF, E);
+ return false;
+}
+
+template <typename AtomicSubsumptionEvaluator>
+bool FoldExpandedConstraint::subsumes(
+ const FoldExpandedConstraint &Other,
+ const AtomicSubsumptionEvaluator &E) const {
+
+ // [C++26] [temp.constr.order]
+ // a fold expanded constraint A subsumes another fold expanded constraint B if
+ // they are compatible for subsumption, have the same fold-operator, and the
+ // constraint of A subsumes that of B
+
+ if (Kind != Other.Kind || !AreCompatibleForSubsumption(*this, Other))
+ return false;
+
+ const NormalForm PDNF = makeDNF(this->Constraint);
+ const NormalForm QCNF = makeCNF(Other.Constraint);
----------------
AaronBallman wrote:
Top-level `const`
https://github.com/llvm/llvm-project/pull/98160
More information about the cfe-commits
mailing list