@@ -75,26 +75,6 @@ struct AtomicConstraint {
75
75
}
76
76
};
77
77
78
- struct FoldExpandedConstraint ;
79
-
80
- using NormalFormConstraint =
81
- llvm::PointerUnion<AtomicConstraint *, FoldExpandedConstraint *>;
82
- struct NormalizedConstraint ;
83
- using NormalForm =
84
- llvm::SmallVector<llvm::SmallVector<NormalFormConstraint, 2 >, 4 >;
85
-
86
- // A constraint is in conjunctive normal form when it is a conjunction of
87
- // clauses where each clause is a disjunction of atomic constraints. For atomic
88
- // constraints A, B, and C, the constraint A ∧ (B ∨ C) is in conjunctive
89
- // normal form.
90
- NormalForm makeCNF (const NormalizedConstraint &Normalized);
91
-
92
- // A constraint is in disjunctive normal form when it is a disjunction of
93
- // clauses where each clause is a conjunction of atomic constraints. For atomic
94
- // constraints A, B, and C, the disjunctive normal form of the constraint A
95
- // ∧ (B ∨ C) is (A ∧ B) ∨ (A ∧ C).
96
- NormalForm makeDNF (const NormalizedConstraint &Normalized);
97
-
98
78
// / \brief A normalized constraint, as defined in C++ [temp.constr.normal], is
99
79
// / either an atomic constraint, a conjunction of normalized constraints or a
100
80
// / disjunction of normalized constraints.
@@ -107,17 +87,26 @@ struct NormalizedConstraint {
107
87
std::pair<NormalizedConstraint, NormalizedConstraint> *, 1 ,
108
88
CompoundConstraintKind>;
109
89
110
- llvm::PointerUnion<AtomicConstraint *, FoldExpandedConstraint *,
111
- CompoundConstraint>
112
- Constraint;
90
+ llvm::PointerUnion<AtomicConstraint *, CompoundConstraint> Constraint;
113
91
114
92
NormalizedConstraint (AtomicConstraint *C): Constraint{C} { };
115
- NormalizedConstraint (FoldExpandedConstraint *C) : Constraint{C} {};
116
-
117
93
NormalizedConstraint (ASTContext &C, NormalizedConstraint LHS,
118
- NormalizedConstraint RHS, CompoundConstraintKind Kind);
119
-
120
- NormalizedConstraint (ASTContext &C, const NormalizedConstraint &Other);
94
+ NormalizedConstraint RHS, CompoundConstraintKind Kind)
95
+ : Constraint{CompoundConstraint{
96
+ new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
97
+ std::move (LHS), std::move (RHS)}, Kind}} { };
98
+
99
+ NormalizedConstraint (ASTContext &C, const NormalizedConstraint &Other) {
100
+ if (Other.isAtomic ()) {
101
+ Constraint = new (C) AtomicConstraint (*Other.getAtomicConstraint ());
102
+ } else {
103
+ Constraint = CompoundConstraint (
104
+ new (C) std::pair<NormalizedConstraint, NormalizedConstraint>{
105
+ NormalizedConstraint (C, Other.getLHS ()),
106
+ NormalizedConstraint (C, Other.getRHS ())},
107
+ Other.getCompoundKind ());
108
+ }
109
+ }
121
110
NormalizedConstraint (NormalizedConstraint &&Other):
122
111
Constraint (Other.Constraint) {
123
112
Other.Constraint = nullptr ;
@@ -131,24 +120,20 @@ struct NormalizedConstraint {
131
120
return *this ;
132
121
}
133
122
134
- bool isAtomic () const { return Constraint.is <AtomicConstraint *>(); }
135
- bool isFoldExpanded () const {
136
- return Constraint.is <FoldExpandedConstraint *>();
137
- }
138
- bool isCompound () const { return Constraint.is <CompoundConstraint>(); }
139
-
140
123
CompoundConstraintKind getCompoundKind () const {
141
- assert (isCompound () && " getCompoundKind on a non-compound constraint. ." );
124
+ assert (! isAtomic () && " getCompoundKind called on atomic constraint." );
142
125
return Constraint.get <CompoundConstraint>().getInt ();
143
126
}
144
127
128
+ bool isAtomic () const { return Constraint.is <AtomicConstraint *>(); }
129
+
145
130
NormalizedConstraint &getLHS () const {
146
- assert (isCompound () && " getLHS called on a non-compound constraint." );
131
+ assert (! isAtomic () && " getLHS called on atomic constraint." );
147
132
return Constraint.get <CompoundConstraint>().getPointer ()->first ;
148
133
}
149
134
150
135
NormalizedConstraint &getRHS () const {
151
- assert (isCompound () && " getRHS called on a non-compound constraint." );
136
+ assert (! isAtomic () && " getRHS called on atomic constraint." );
152
137
return Constraint.get <CompoundConstraint>().getPointer ()->second ;
153
138
}
154
139
@@ -158,125 +143,13 @@ struct NormalizedConstraint {
158
143
return Constraint.get <AtomicConstraint *>();
159
144
}
160
145
161
- FoldExpandedConstraint *getFoldExpandedConstraint () const {
162
- assert (isFoldExpanded () &&
163
- " getFoldExpandedConstraint called on non-fold-expanded constraint." );
164
- return Constraint.get <FoldExpandedConstraint *>();
165
- }
166
-
167
146
private:
168
147
static std::optional<NormalizedConstraint>
169
148
fromConstraintExprs (Sema &S, NamedDecl *D, ArrayRef<const Expr *> E);
170
149
static std::optional<NormalizedConstraint>
171
150
fromConstraintExpr (Sema &S, NamedDecl *D, const Expr *E);
172
151
};
173
152
174
- struct FoldExpandedConstraint {
175
- enum class FoldOperatorKind { And, Or } Kind;
176
- NormalizedConstraint Constraint;
177
- const Expr *Pattern;
178
-
179
- FoldExpandedConstraint (FoldOperatorKind K, NormalizedConstraint C,
180
- const Expr *Pattern)
181
- : Kind(K), Constraint(std::move(C)), Pattern(Pattern) {};
182
-
183
- template <typename AtomicSubsumptionEvaluator>
184
- bool subsumes (const FoldExpandedConstraint &Other,
185
- const AtomicSubsumptionEvaluator &E) const ;
186
-
187
- static bool AreCompatibleForSubsumption (const FoldExpandedConstraint &A,
188
- const FoldExpandedConstraint &B);
189
- };
190
-
191
- const NormalizedConstraint *getNormalizedAssociatedConstraints (
192
- Sema &S, NamedDecl *ConstrainedDecl,
193
- ArrayRef<const Expr *> AssociatedConstraints);
194
-
195
- template <typename AtomicSubsumptionEvaluator>
196
- bool subsumes (const NormalForm &PDNF, const NormalForm &QCNF,
197
- const AtomicSubsumptionEvaluator &E) {
198
- // C++ [temp.constr.order] p2
199
- // Then, P subsumes Q if and only if, for every disjunctive clause Pi in the
200
- // disjunctive normal form of P, Pi subsumes every conjunctive clause Qj in
201
- // the conjuctive normal form of Q, where [...]
202
- for (const auto &Pi : PDNF) {
203
- for (const auto &Qj : QCNF) {
204
- // C++ [temp.constr.order] p2
205
- // - [...] a disjunctive clause Pi subsumes a conjunctive clause Qj if
206
- // and only if there exists an atomic constraint Pia in Pi for which
207
- // there exists an atomic constraint, Qjb, in Qj such that Pia
208
- // subsumes Qjb.
209
- bool Found = false ;
210
- for (NormalFormConstraint Pia : Pi) {
211
- for (NormalFormConstraint Qjb : Qj) {
212
- if (Pia.is <FoldExpandedConstraint *>() &&
213
- Qjb.is <FoldExpandedConstraint *>()) {
214
- if (Pia.get <FoldExpandedConstraint *>()->subsumes (
215
- *Qjb.get <FoldExpandedConstraint *>(), E)) {
216
- Found = true ;
217
- break ;
218
- }
219
- } else if (Pia.is <AtomicConstraint *>() &&
220
- Qjb.is <AtomicConstraint *>()) {
221
- if (E (*Pia.get <AtomicConstraint *>(),
222
- *Qjb.get <AtomicConstraint *>())) {
223
- Found = true ;
224
- break ;
225
- }
226
- }
227
- }
228
- if (Found)
229
- break ;
230
- }
231
- if (!Found)
232
- return false ;
233
- }
234
- }
235
- return true ;
236
- }
237
-
238
- template <typename AtomicSubsumptionEvaluator>
239
- bool subsumes (Sema &S, NamedDecl *DP, ArrayRef<const Expr *> P, NamedDecl *DQ,
240
- ArrayRef<const Expr *> Q, bool &Subsumes,
241
- const AtomicSubsumptionEvaluator &E) {
242
- // C++ [temp.constr.order] p2
243
- // In order to determine if a constraint P subsumes a constraint Q, P is
244
- // transformed into disjunctive normal form, and Q is transformed into
245
- // conjunctive normal form. [...]
246
- const NormalizedConstraint *PNormalized =
247
- getNormalizedAssociatedConstraints (S, DP, P);
248
- if (!PNormalized)
249
- return true ;
250
- NormalForm PDNF = makeDNF (*PNormalized);
251
-
252
- const NormalizedConstraint *QNormalized =
253
- getNormalizedAssociatedConstraints (S, DQ, Q);
254
- if (!QNormalized)
255
- return true ;
256
- NormalForm QCNF = makeCNF (*QNormalized);
257
-
258
- Subsumes = subsumes (PDNF, QCNF, E);
259
- return false ;
260
- }
261
-
262
- template <typename AtomicSubsumptionEvaluator>
263
- bool FoldExpandedConstraint::subsumes (
264
- const FoldExpandedConstraint &Other,
265
- const AtomicSubsumptionEvaluator &E) const {
266
-
267
- // [C++26] [temp.constr.order]
268
- // a fold expanded constraint A subsumes another fold expanded constraint B if
269
- // they are compatible for subsumption, have the same fold-operator, and the
270
- // constraint of A subsumes that of B
271
-
272
- if (Kind != Other.Kind || !AreCompatibleForSubsumption (*this , Other))
273
- return false ;
274
-
275
- NormalForm PDNF = makeDNF (this ->Constraint );
276
- NormalForm QCNF = makeCNF (Other.Constraint );
277
- return clang::subsumes (PDNF, QCNF, E);
278
- }
279
-
280
153
} // clang
281
154
282
155
#endif // LLVM_CLANG_SEMA_SEMACONCEPT_H
0 commit comments