C++: respond to further PR comments

This commit is contained in:
Robert Marsh
2018-12-12 16:50:26 -08:00
parent ae4ffd9166
commit 89148a9ec7
9 changed files with 146 additions and 104 deletions

View File

@@ -295,7 +295,7 @@ class IRGuardCondition extends Instruction {
* return x; * return x;
* ``` * ```
*/ */
predicate controlsEdgeDirectly(ConditionalBranchInstruction branch, IRBlock succ, boolean testIsTrue) { predicate hasBranchEdge(ConditionalBranchInstruction branch, IRBlock succ, boolean testIsTrue) {
branch.getCondition() = this and branch.getCondition() = this and
( (
testIsTrue = true and testIsTrue = true and

View File

@@ -751,6 +751,9 @@ class BinaryInstruction extends Instruction {
result = getAnOperand().(RightOperand).getDefinitionInstruction() result = getAnOperand().(RightOperand).getDefinitionInstruction()
} }
/**
* Holds if this instruction's operands are `op1` and `op2`, in either order.
*/
final predicate hasOperands(Operand op1, Operand op2) { final predicate hasOperands(Operand op1, Operand op2) {
op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand) op1 = getAnOperand().(LeftOperand) and op2 = getAnOperand().(RightOperand)
or or

View File

@@ -83,6 +83,10 @@ class ValueNumber extends TValueNumber {
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock() instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
) )
} }
final Operand getAUse() {
this = valueNumber(result.getDefinitionInstruction())
}
} }
/** /**
@@ -220,6 +224,13 @@ ValueNumber valueNumber(Instruction instr) {
) )
} }
/**
* Gets the value number assigned to `instr`, if any. Returns at most one result.
*/
ValueNumber valueNumberOfOperand(Operand op) {
result = valueNumber(op.getDefinitionInstruction())
}
/** /**
* Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique * Gets the value number assigned to `instr`, if any, unless that instruction is assigned a unique
* value number. * value number.

View File

@@ -6,10 +6,6 @@ private newtype TBound =
TBoundInstruction(Instruction i) { TBoundInstruction(Instruction i) {
i.getResultType() instanceof IntegralType or i.getResultType() instanceof IntegralType or
i.getResultType() instanceof PointerType i.getResultType() instanceof PointerType
} or
TBoundOperand(Operand o) {
o.getDefinitionInstruction().getResultType() instanceof IntegralType or
o.getDefinitionInstruction().getResultType() instanceof PointerType
} }
/** /**
@@ -53,23 +49,3 @@ class InstructionBound extends Bound, TBoundInstruction {
getInstruction().getLocation().hasLocationInfo(path, sl, sc, el, ec) getInstruction().getLocation().hasLocationInfo(path, sl, sc, el, ec)
} }
} }
/**
* A bound corresponding to the value of an `Operand`.
*/
class OperandBound extends Bound, TBoundOperand {
Operand getOperand() {
this = TBoundOperand(result)
}
override Instruction getInstruction(int delta) {
this = TBoundOperand(result.getAUse()) and
delta = 0
}
override string toString() { result = getOperand().toString() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
getOperand().getLocation().hasLocationInfo(path, sl, sc, el, ec)
}
}

View File

@@ -124,14 +124,10 @@ import RangeAnalysisPublic
* - `isEq = true` : `i == bound + delta` * - `isEq = true` : `i == bound + delta`
* - `isEq = false` : `i != bound + delta` * - `isEq = false` : `i != bound + delta`
*/ */
private IRGuardCondition eqFlowCond(Operand op, Operand bound, int delta, private IRGuardCondition eqFlowCond(ValueNumber vn, Operand bound, int delta,
boolean isEq, boolean testIsTrue) boolean isEq, boolean testIsTrue)
{ {
exists(Operand compared | result.comparesEq(vn.getAUse(), bound, delta, isEq, testIsTrue)
result.ensuresEq(compared, bound, delta, op.getInstruction().getBlock(), isEq) and
result.controls(bound.getInstruction().getBlock(), testIsTrue) and
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
)
} }
/** /**
@@ -147,8 +143,9 @@ private predicate boundFlowStepSsa(
reason = TNoReason() and reason = TNoReason() and
delta = 0 delta = 0
or*/ or*/
exists(IRGuardCondition guard | exists(IRGuardCondition guard, boolean testIsTrue |
guard = boundFlowCond(op2, op1, delta, upper, _) and guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
guard.controls(op2.getInstruction().getBlock(), testIsTrue) and
reason = TCondReason(guard) reason = TCondReason(guard)
) )
} }
@@ -160,37 +157,19 @@ private predicate boundFlowStepSsa(
* - `upper = true` : `op <= bound + delta` * - `upper = true` : `op <= bound + delta`
* - `upper = false` : `op >= bound + delta` * - `upper = false` : `op >= bound + delta`
*/ */
private IRGuardCondition boundFlowCond(NonPhiOperand op, NonPhiOperand bound, int delta, boolean upper, private IRGuardCondition boundFlowCond(ValueNumber vn, NonPhiOperand bound, int delta, boolean upper,
boolean testIsTrue) boolean testIsTrue)
{ {
exists(Operand compared | exists(int d |
result.comparesLt(compared, bound, delta, upper, testIsTrue) and result.comparesLt(vn.getAUse(), bound, d, upper, testIsTrue) and
result.controls(op.getInstruction().getBlock(), testIsTrue) and // strengthen from x < y to x <= y-1
valueNumber(compared.getDefinitionInstruction()) = valueNumber(op.getDefinitionInstruction()) if upper = true
) then delta = d-1
// TODO: strengthening through modulus library else delta = d
}
/**
* Gets a condition that tests whether `op` is bounded by `bound + delta`.
*
* - `upper = true` : `op <= bound + delta`
* - `upper = false` : `op >= bound + delta`
*/
private IRGuardCondition boundFlowCondPhi(PhiOperand op, NonPhiOperand bound, int delta, boolean upper,
boolean testIsTrue)
{
exists(Operand compared |
result.comparesLt(compared, bound, delta, upper, testIsTrue) and
result.controlsEdgeDirectly(op.getPredecessorBlock().getLastInstruction(), op.getInstruction().getBlock(), testIsTrue) and
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
) )
or or
exists(Operand compared | result = eqFlowCond(vn, bound, delta, true, testIsTrue) and
result.comparesLt(compared, bound, delta, upper, testIsTrue) and (upper = true or upper = false)
result.controls(op.getPredecessorBlock(), testIsTrue) and
valueNumber(compared.getDefinitionInstruction()) = valueNumber (op.getDefinitionInstruction())
)
// TODO: strengthening through modulus library // TODO: strengthening through modulus library
} }
@@ -239,6 +218,9 @@ private predicate safeCast(IntegralType fromtyp, IntegralType totyp) {
private class SafeCastInstruction extends ConvertInstruction { private class SafeCastInstruction extends ConvertInstruction {
SafeCastInstruction() { SafeCastInstruction() {
safeCast(getResultType(), getOperand().getResultType()) safeCast(getResultType(), getOperand().getResultType())
or
getResultType() instanceof PointerType and
getOperand().getResultType() instanceof PointerType
} }
} }
@@ -402,8 +384,13 @@ private predicate boundFlowStepPhi(
reason = TNoReason() and reason = TNoReason() and
delta = 0 delta = 0
or or
exists(IRGuardCondition guard | exists(IRGuardCondition guard, boolean testIsTrue |
guard = boundFlowCondPhi(op2, op1, delta, upper, _) and guard = boundFlowCond(valueNumberOfOperand(op2), op1, delta, upper, testIsTrue) and
(
guard.hasBranchEdge(op2.getPredecessorBlock().getLastInstruction(), op2.getInstruction().getBlock(), testIsTrue)
or
guard.controls(op2.getPredecessorBlock(), testIsTrue)
) and
reason = TCondReason(guard) reason = TCondReason(guard)
) )
} }
@@ -476,8 +463,6 @@ private predicate boundedPhiInp(
) { ) {
phi.getAnOperand() = op and phi.getAnOperand() = op and
exists(int d, boolean fromBackEdge0 | exists(int d, boolean fromBackEdge0 |
boundedInstruction(op.getDefinitionInstruction(), b, d, upper, fromBackEdge0, origdelta, reason)
or
boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason) boundedPhiOperand(op, b, d, upper, fromBackEdge0, origdelta, reason)
or or
b.(InstructionBound).getInstruction() = op.getDefinitionInstruction() and b.(InstructionBound).getInstruction() = op.getDefinitionInstruction() and
@@ -564,6 +549,7 @@ private predicate boundedInstruction(
boundedPhiCandValidForEdge(i, b, delta, upper, fromBackEdge, origdelta, reason, op) boundedPhiCandValidForEdge(i, b, delta, upper, fromBackEdge, origdelta, reason, op)
) )
or or
not i instanceof PhiInstruction and
i = b.getInstruction(delta) and i = b.getInstruction(delta) and
(upper = true or upper = false) and (upper = true or upper = false) and
fromBackEdge = false and fromBackEdge = false and

View File

@@ -44,4 +44,21 @@ predicate valueFlowStep(Instruction i, Operand op, int delta) {
| |
delta = -getValue(getConstantValue(x.getDefinitionInstruction())) delta = -getValue(getConstantValue(x.getDefinitionInstruction()))
) )
or
exists(Operand x |
i.(PointerAddInstruction).getAnOperand() = op and
i.(PointerAddInstruction).getAnOperand() = x and
op != x
|
delta = i.(PointerAddInstruction).getElementSize() *
getValue(getConstantValue(x.getDefinitionInstruction()))
)
or
exists(Operand x |
i.(PointerSubInstruction).getAnOperand().(LeftOperand) = op and
i.(PointerSubInstruction).getAnOperand().(RightOperand) = x
|
delta = i.(PointerSubInstruction).getElementSize() *
-getValue(getConstantValue(x.getDefinitionInstruction()))
)
} }

View File

@@ -1,26 +1,39 @@
| test.cpp:8:9:8:9 | Load: y | test.cpp:6:15:6:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... | | test.cpp:10:10:10:10 | Store: x | test.cpp:6:15:6:15 | InitializeParameter: x | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:15:6:15 | InitializeParameter: x | 0 | false | NoReason | | test.cpp:10:10:10:10 | Store: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... | test.cpp:7:7:7:11 | test.cpp:7:7:7:11 |
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... | | test.cpp:10:10:10:10 | Store: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:10:10:10:10 | Load: x | test.cpp:6:22:6:22 | InitializeParameter: y | 0 | false | NoReason | | test.cpp:20:10:20:10 | Store: x | test.cpp:14:15:14:15 | InitializeParameter: x | -2 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:16:9:16:9 | Load: y | test.cpp:14:15:14:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... | | test.cpp:20:10:20:10 | Store: x | test.cpp:14:22:14:22 | InitializeParameter: y | -2 | false | CompareLT: ... < ... | test.cpp:15:7:15:11 | test.cpp:15:7:15:11 |
| test.cpp:18:9:18:9 | Load: x | test.cpp:14:22:14:22 | InitializeParameter: y | 0 | false | CompareLT: ... < ... | | test.cpp:27:10:27:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:20:10:20:10 | Load: x | test.cpp:14:15:14:15 | InitializeParameter: x | -2 | false | NoReason | | test.cpp:27:10:27:10 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | -1 | true | CompareLT: ... < ... | test.cpp:26:14:26:18 | test.cpp:26:14:26:18 |
| test.cpp:20:10:20:10 | Load: x | test.cpp:14:22:14:22 | InitializeParameter: y | -2 | false | CompareLT: ... < ... | | test.cpp:27:10:27:10 | Load: i | test.cpp:26:18:26:18 | Load: x | -1 | true | CompareLT: ... < ... | test.cpp:26:14:26:18 | test.cpp:26:14:26:18 |
| test.cpp:26:14:26:14 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | | test.cpp:30:10:30:10 | Load: i | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... | test.cpp:29:14:29:18 | test.cpp:29:14:29:18 |
| test.cpp:26:21:26:23 | Load: ... ++ | file://:0:0:0:0 | 0 | 0 | false | NoReason | | test.cpp:30:10:30:10 | Load: i | test.cpp:29:18:29:18 | Constant: 0 | 1 | false | CompareGT: ... > ... | test.cpp:29:14:29:18 | test.cpp:29:14:29:18 |
| test.cpp:26:21:26:23 | Load: ... ++ | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | CompareLT: ... < ... | | test.cpp:33:10:33:10 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:27:7:27:7 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | | test.cpp:33:10:33:10 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
| test.cpp:27:7:27:7 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | CompareLT: ... < ... | | test.cpp:33:10:33:10 | Load: i | test.cpp:26:14:26:14 | Load: i | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
| test.cpp:29:14:29:14 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason | | test.cpp:33:10:33:10 | Load: i | test.cpp:32:18:32:18 | Load: x | 1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
| test.cpp:29:21:29:23 | Load: ... -- | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... | | test.cpp:33:10:33:10 | Load: i | test.cpp:32:18:32:22 | Add: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:32:14:32:22 | test.cpp:32:14:32:22 |
| test.cpp:29:21:29:23 | Load: ... -- | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason | | test.cpp:40:10:40:14 | Load: begin | test.cpp:38:28:38:30 | InitializeParameter: end | -1 | true | CompareLT: ... < ... | test.cpp:39:10:39:20 | test.cpp:39:10:39:20 |
| test.cpp:30:7:30:7 | Load: i | file://:0:0:0:0 | 0 | 1 | false | CompareGT: ... > ... | | test.cpp:40:10:40:14 | Load: begin | test.cpp:39:18:39:20 | Load: end | -1 | true | CompareLT: ... < ... | test.cpp:39:10:39:20 | test.cpp:39:10:39:20 |
| test.cpp:30:7:30:7 | Load: i | test.cpp:24:15:24:15 | InitializeParameter: x | 0 | true | NoReason | | test.cpp:49:12:49:12 | Load: x | test.cpp:46:22:46:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
| test.cpp:37:6:37:10 | Load: begin | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... | | test.cpp:49:12:49:12 | Load: x | test.cpp:46:29:46:29 | InitializeParameter: z | -2 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
| test.cpp:37:16:37:20 | Load: begin | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... | | test.cpp:49:12:49:12 | Load: x | test.cpp:47:11:47:11 | Load: z | -2 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
| test.cpp:38:5:38:11 | Load: ... ++ | test.cpp:35:28:35:30 | InitializeParameter: end | 0 | true | CompareLT: ... < ... | | test.cpp:49:12:49:12 | Load: x | test.cpp:48:13:48:13 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:48:9:48:13 | test.cpp:48:9:48:13 |
| test.cpp:44:13:44:13 | Load: y | test.cpp:42:29:42:29 | InitializeParameter: z | 0 | true | CompareLT: ... < ... | | test.cpp:54:12:54:12 | Load: x | test.cpp:46:22:46:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:52:7:52:11 | test.cpp:52:7:52:11 |
| test.cpp:45:12:45:12 | Load: x | test.cpp:42:22:42:22 | InitializeParameter: y | 0 | true | CompareLT: ... < ... | | test.cpp:54:12:54:12 | Load: x | test.cpp:52:11:52:11 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:52:7:52:11 | test.cpp:52:7:52:11 |
| test.cpp:45:12:45:12 | Load: x | test.cpp:42:29:42:29 | InitializeParameter: z | 0 | true | CompareLT: ... < ... | | test.cpp:62:10:62:13 | Load: iter | test.cpp:60:17:60:17 | InitializeParameter: p | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:49:9:49:9 | Load: y | test.cpp:42:15:42:15 | InitializeParameter: x | 1 | false | CompareLT: ... < ... | | test.cpp:62:10:62:13 | Load: iter | test.cpp:61:39:61:51 | Convert: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:50:12:50:12 | Load: x | test.cpp:42:22:42:22 | InitializeParameter: y | 0 | true | CompareLT: ... < ... | | test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:48 | Load: p | 3 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:62:10:62:13 | Load: iter | test.cpp:61:48:61:50 | PointerAdd: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:61:32:61:51 | test.cpp:61:32:61:51 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:60:17:60:17 | InitializeParameter: p | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:61:32:61:35 | Load: iter | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:15:65:27 | Convert: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:15:65:27 | Store: (char *)... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:24:65:24 | Load: p | 3 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:65:24:65:26 | PointerAdd: ... + ... | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:67:10:67:13 | Load: iter | test.cpp:66:39:66:41 | Load: end | -1 | true | CompareLT: ... < ... | test.cpp:66:32:66:41 | test.cpp:66:32:66:41 |
| test.cpp:77:12:77:12 | Load: i | file://:0:0:0:0 | 0 | 0 | false | NoReason | file://:0:0:0:0 | file://:0:0:0:0 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:15:72:15 | InitializeParameter: x | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:72:22:72:22 | InitializeParameter: y | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:75:7:75:7 | Load: x | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |
| test.cpp:77:12:77:12 | Load: i | test.cpp:76:24:76:24 | Load: y | -1 | true | CompareLT: ... < ... | test.cpp:76:20:76:24 | test.cpp:76:20:76:24 |

View File

@@ -3,14 +3,23 @@ import semmle.code.cpp.ir.IR
import semmle.code.cpp.controlflow.IRGuards import semmle.code.cpp.controlflow.IRGuards
import semmle.code.cpp.ir.ValueNumbering import semmle.code.cpp.ir.ValueNumbering
query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upper, Reason reason) query predicate instructionBounds(Instruction i, Bound b, int delta, boolean upper, Reason reason,
Location reasonLoc)
{ {
i instanceof LoadInstruction and
boundedInstruction(i, b, delta, upper, reason) and
( (
b.(InstructionBound).getInstruction() instanceof InitializeParameterInstruction or i.getAUse() instanceof ArgumentOperand
b.(InstructionBound).getInstruction() instanceof CallInstruction or or
b instanceof ZeroBound i.getAUse() instanceof ReturnValueOperand
) and ) and
not valueNumber(b.(InstructionBound).getInstruction()) = valueNumber(i) (
upper = true and
delta = min(int d | boundedInstruction(i, b, d, upper, reason))
or
upper = false and
delta = max(int d | boundedInstruction(i, b, d, upper, reason))
) and
not valueNumber(b.getInstruction()) = valueNumber(i)
and if reason instanceof CondReason
then reasonLoc = reason.(CondReason).getCond().getLocation()
else reasonLoc instanceof UnknownDefaultLocation
} }

View File

@@ -21,24 +21,28 @@ int test2(int x, int y) {
} }
// for loops // for loops
int test3(int x, int *p) { int test3(int x) {
int i; int i;
for(i = 0; i < x; i++) { for(i = 0; i < x; i++) {
p[i]; sink(i);
} }
for(i = x; i > 0; i--) { for(i = x; i > 0; i--) {
p[i]; sink(i);
}
for(i = 0; i < x + 2; i++) {
sink(i);
} }
} }
// pointer bounds // pointer bounds
int test4(int *begin, int *end) { int test4(int *begin, int *end) {
while (begin < end) { while (begin < end) {
*begin = (*begin) + 1; sink(begin);
begin++; begin++;
} }
} }
// bound propagation through conditionals
int test5(int x, int y, int z) { int test5(int x, int y, int z) {
if (y < z) { if (y < z) {
if (x < y) { if (x < y) {
@@ -51,3 +55,26 @@ int test5(int x, int y, int z) {
} }
} }
} }
// pointer arithmetic and sizes
void test6(int *p) {
for (char *iter = (char *)p; iter < (char *)(p+1); iter++) {
sink(iter);
}
char *end = (char *)(p+1);
for (char *iter = (char *)p; iter < end; iter++) {
sink(iter);
}
}
// inference from equality
int test8(int x, int y) {
int *p = new int[x];
if (x == y) {
for(int i = 0; i < y; ++i) {
sink(i);
}
}
}