|
12 | 12 | #include "pointer_logic.h" |
13 | 13 |
|
14 | 14 | #include <util/arith_tools.h> |
| 15 | +#include <util/byte_operators.h> |
15 | 16 | #include <util/c_types.h> |
16 | 17 | #include <util/invariant.h> |
17 | 18 | #include <util/pointer_offset_size.h> |
@@ -98,76 +99,35 @@ exprt pointer_logict::pointer_expr( |
98 | 99 |
|
99 | 100 | const exprt &object_expr=objects[pointer.object]; |
100 | 101 |
|
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 = get_subexpression_at_offset( |
| 108 | + 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) |
112 | 120 | { |
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())); |
128 | 124 | } |
129 | | - else if(src.type().id()==ID_struct) |
| 125 | + else |
130 | 126 | { |
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())); |
166 | 130 | } |
167 | | - else if(src.type().id()==ID_union) |
168 | | - return src; |
169 | | - |
170 | | - return src; |
171 | 131 | } |
172 | 132 |
|
173 | 133 | pointer_logict::pointer_logict(const namespacet &_ns):ns(_ns) |
|
0 commit comments