Skip to content

Commit d4296f1

Browse files
committed
Use get_subexpression_at_offset in pointer_logict
We now support pointers into structs with zero-sized members, which is a GCC extension that we otherwise do support.
1 parent 044b004 commit d4296f1

File tree

4 files changed

+60
-71
lines changed

4 files changed

+60
-71
lines changed

regression/cbmc/Empty_struct2/main.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
3+
struct empty
4+
{
5+
};
6+
7+
#pragma pack(1)
8+
struct S
9+
{
10+
char x;
11+
struct empty e;
12+
char y;
13+
};
14+
#pragma pack()
15+
16+
int main()
17+
{
18+
struct S s;
19+
assert(sizeof(struct S) == 2);
20+
21+
struct empty *p = &s.e;
22+
23+
assert(p == (char *)&s + 1);
24+
25+
return 0;
26+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/solvers/flattening/pointer_logic.cpp

Lines changed: 26 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected]
1212
#include "pointer_logic.h"
1313

1414
#include <util/arith_tools.h>
15+
#include <util/byte_operators.h>
1516
#include <util/c_types.h>
1617
#include <util/invariant.h>
1718
#include <util/pointer_offset_size.h>
@@ -98,76 +99,35 @@ exprt pointer_logict::pointer_expr(
9899

99100
const exprt &object_expr=objects[pointer.object];
100101

101-
exprt deep_object=object_rec(pointer.offset, type, object_expr);
102-
103-
return address_of_exprt(deep_object, type);
104-
}
105-
106-
exprt pointer_logict::object_rec(
107-
const mp_integer &offset,
108-
const typet &pointer_type,
109-
const exprt &src) const
110-
{
111-
if(src.type().id()==ID_array)
102+
typet subtype = type.subtype();
103+
// This is a gcc extension.
104+
// https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Pointer-Arith.html
105+
if(subtype.id() == ID_empty)
106+
subtype = char_type();
107+
const exprt deep_object =
108+
get_subexpression_at_offset(object_expr, pointer.offset, subtype, ns);
109+
CHECK_RETURN(deep_object.is_not_nil());
110+
if(deep_object.id() != byte_extract_id())
111+
return address_of_exprt(deep_object, type);
112+
113+
const byte_extract_exprt &be = to_byte_extract_expr(deep_object);
114+
if(be.offset().is_zero())
115+
return address_of_exprt(be.op(), type);
116+
117+
const auto subtype_bytes = pointer_offset_size(subtype, ns);
118+
CHECK_RETURN(subtype_bytes.has_value() && *subtype_bytes > 0);
119+
if(*subtype_bytes > pointer.offset)
112120
{
113-
auto size = pointer_offset_size(src.type().subtype(), ns);
114-
115-
if(!size.has_value() || *size == 0)
116-
return src;
117-
118-
mp_integer index = offset / (*size);
119-
mp_integer rest = offset % (*size);
120-
if(rest<0)
121-
rest=-rest;
122-
123-
index_exprt tmp(src.type().subtype());
124-
tmp.index()=from_integer(index, typet(ID_integer));
125-
tmp.array()=src;
126-
127-
return object_rec(rest, pointer_type, tmp);
121+
return plus_exprt(
122+
address_of_exprt(be.op(), pointer_type(char_type())),
123+
from_integer(pointer.offset, index_type()));
128124
}
129-
else if(src.type().id()==ID_struct)
125+
else
130126
{
131-
const struct_typet::componentst &components=
132-
to_struct_type(src.type()).components();
133-
134-
if(offset<0)
135-
return src;
136-
137-
mp_integer current_offset=0;
138-
139-
for(const auto &c : components)
140-
{
141-
INVARIANT(
142-
offset >= current_offset,
143-
"when the object has not been found yet its offset must not be smaller"
144-
"than the offset of the current struct component");
145-
146-
const typet &subtype=c.type();
147-
148-
const auto sub_size = pointer_offset_size(subtype, ns);
149-
CHECK_RETURN(sub_size.has_value() && *sub_size != 0);
150-
151-
mp_integer new_offset = current_offset + *sub_size;
152-
153-
if(new_offset>offset)
154-
{
155-
// found it
156-
member_exprt tmp(src, c);
157-
158-
return object_rec(
159-
offset-current_offset, pointer_type, tmp);
160-
}
161-
162-
current_offset=new_offset;
163-
}
164-
165-
return src;
127+
return plus_exprt(
128+
address_of_exprt(be.op(), pointer_type(char_type())),
129+
from_integer(pointer.offset / *subtype_bytes, index_type()));
166130
}
167-
else if(src.type().id()==ID_union)
168-
return src;
169-
170-
return src;
171131
}
172132

173133
pointer_logict::pointer_logict(const namespacet &_ns):ns(_ns)

src/solvers/flattening/pointer_logic.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,6 @@ class pointer_logict
7878
exprt pointer_expr(
7979
const mp_integer &offset,
8080
const exprt &object) const;
81-
82-
exprt object_rec(
83-
const mp_integer &offset,
84-
const typet &pointer_type,
85-
const exprt &src) const;
8681
};
8782

8883
#endif // CPROVER_SOLVERS_FLATTENING_POINTER_LOGIC_H

0 commit comments

Comments
 (0)