1+ import swift as swift
2+ import qtil.parameterization.SignatureTypes
3+
4+ /**
5+ * A module for dealing with pairs of exclusive operands in C++ ASTs.
6+ *
7+ * For instance, to find cases where one operand is an integer and the other is a constant, you
8+ * will want to to perform checks on each operand separately and consistently without worrying about
9+ * order. This module makes this common pattern easy to implement.
10+ *
11+ * This module takes two type parameters:
12+ * - `Operand`: the type of the operands (e.g. `Expr`)
13+ * - `HasOperands`: a type that has operands of type `Operand` (e.g. `BinaryExpr`)
14+ *
15+ * ```ql
16+ * // Using this module:
17+ * predicate myBinaryTestNew(BinaryExpr e) {
18+ * exists(TwoOperands<BinaryExpr>::Set set |
19+ * set.getOperation() = e and
20+ * set.someOperand().isInteger() and
21+ * set.otherOperand().isConstant()
22+ * )
23+ * }
24+ *
25+ * // Is roughly equivalent to:
26+ * predicate myBinaryTestOld(BinaryExpr e) {
27+ * exists(Expr a, Expr b |
28+ * e.getAnOperand() = a and
29+ * e.getAnOperand() = b and
30+ * a != b and
31+ * a.isInteger() and
32+ * b.isConstant()
33+ * )
34+ * }
35+ * ```
36+ *
37+ * Some caution about using this module: for each use, two `Set` objects exst. If you do not
38+ * properly constrain the usage of `someOperand()` and `otherOperand()`, then these members could
39+ * hold for different `Set`s. Therefore, `someOperand()` and `otherOperand()` may be the same
40+ * operand. This will not happen if the `Set` is properly constrained across the two member
41+ * invocations.
42+ *
43+ * ```ql
44+ * predicate bug(BinaryExpr e) {
45+ * // Bad: the two sets are not constrained to the same instance, therefore the operands not
46+ * // guaranteed to be different.
47+ * TwoOperands<BinaryExpr>::getASet(e).someOperand().isInteger() and
48+ * TwoOperands<BinaryExpr>::getASet(e).otherOperand().isConstant()
49+ * }
50+ * ```
51+ */
52+ module TwoOperands< Signature< swift:: BinaryExpr > :: Type BinOp> {
53+ private import qtil.ast.TwoOperands as Make
54+ import Make:: TwoOperands< swift:: Expr , BinOp >
55+ }
0 commit comments