Skip to content

Commit 5b19b26

Browse files
committed
Add special case for deref-of-typecast-of-if
This results from expressions such as *(int*)*p, and is very nearly as easy to handle as the already-special-cased deref-of-if case. In essence we transform *(type*)(x ? y : z) into x ? *(type*)y : *(type*)z, which should yield a more compact expression due to not conflating the alias sets that can be derived from the two arms of the conditional.
1 parent edf0639 commit 5b19b26

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

regression/cbmc/double_deref/README

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ result = (derefd_pointer == &o3 ? o3 : derefd_pointer == &o4 ? o4 : derefd_point
2020

2121
The tests in this directory check that auxiliary let-expressions like this are only used when appropriate by inspecting formula VCCs:
2222
double_deref.desc -- a directly nested double-dereference, should not use a let-expression
23-
double_deref_with_cast.desc -- a double-deref with an intervening cast (*(int*)*p for example), should use a let-expression
23+
double_deref_with_cast.desc -- a double-deref with an intervening cast (*(int*)*p for example), should not use a let-expression
2424
double_deref_with_member.desc -- a double-deref with an intervening member expression (p->field1->field2), should use a let-expression
2525
double_deref_with_pointer_arithmetic.desc -- a double-deref with intervening pointer arithmetic (p[idx1][idx2]), should use a let-expression
2626
*_single_alias.desc -- variants of the above where the first dereference points to a single possible object, so no let-expression is necessary
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
CORE
22
double_deref_with_cast.c
33
--show-vcc
4-
^\{-[0-9]+\} derefd_pointer::derefd_pointer!0#1 =
5-
^\{1\} \(derefd_pointer::derefd_pointer!0#1 = address_of\(symex_dynamic::dynamic_object[1-9]+\) \? main::argc!0@1#1 = [12] : main::argc!0@1#1 = [12]
4+
\{1\} \(cast\(main::1::pptr!0@1#2, signedbv\[32\]\*\*\) = address_of\(main::1::ptr2!0@1\) \? main::argc!0@1#1 = 2 \: main::argc!0@1#1 = 1\)
65
^EXIT=0$
76
^SIGNAL=0$
87
--
8+
derefd_pointer::derefd_pointer
99
--
1010
See README for details about these tests

src/pointer-analysis/value_set_dereference.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,27 @@ exprt value_set_dereferencet::dereference(const exprt &pointer)
7272
exprt false_case = dereference(if_expr.false_case());
7373
return if_exprt(if_expr.cond(), true_case, false_case);
7474
}
75+
else if(pointer.id() == ID_typecast)
76+
{
77+
const exprt *underlying = &pointer;
78+
// Note this isn't quite the same as skip_typecast, which would also skip
79+
// things such as int-to-ptr typecasts which we shouldn't ignore
80+
while(
81+
underlying->id() == ID_typecast && underlying->type().id() == ID_pointer)
82+
{
83+
underlying = &to_typecast_expr(*underlying).op();
84+
}
85+
86+
if(underlying->id() == ID_if && underlying->type().id() == ID_pointer)
87+
{
88+
const auto &if_expr = to_if_expr(*underlying);
89+
return
90+
if_exprt(
91+
if_expr.cond(),
92+
dereference(typecast_exprt(if_expr.true_case(), pointer.type())),
93+
dereference(typecast_exprt(if_expr.false_case(), pointer.type())));
94+
}
95+
}
7596

7697
// type of the object
7798
const typet &type=pointer.type().subtype();

0 commit comments

Comments
 (0)