|
17 | 17 |
|
18 | 18 | #include <pointer-analysis/dynamic_object_name.h>
|
19 | 19 | #include <util/infix.h>
|
| 20 | +#include <java_bytecode/java_types.h> |
20 | 21 |
|
21 | 22 | // Non-static functions are documented in the header file,
|
22 | 23 | // local_value_set_analysis.h
|
@@ -202,56 +203,73 @@ static const exprt get_expr_from_root_object(
|
202 | 203 | }
|
203 | 204 |
|
204 | 205 | /// Second, follow access path (if non-empty)
|
205 |
| - for(const auto &access_path_entry : access_path_entries) |
| 206 | + for(external_value_set_exprt::access_path_entriest::const_iterator it = |
| 207 | + access_path_entries.begin(); |
| 208 | + it != access_path_entries.end(); |
| 209 | + ++it) |
206 | 210 | {
|
207 |
| - std::string access_path_label = id2string(access_path_entry.label()); |
| 211 | + std::string access_path_label = id2string(it->label()); |
208 | 212 | /// If expr is of type Z and Z <: Y <: X <: ... <: A and we are
|
209 | 213 | /// accessing a field of A then access_path_label will be
|
210 |
| - /// ".@Y.@X.@W. ... [email protected]_name" |
| 214 | + /// ".@Y.@X.@W. ... [email protected]_name". For an array dereference, the access |
| 215 | + /// path will have the label "[]", and the access path entry before |
| 216 | + /// it will have the label ".data". |
211 | 217 | DATA_INVARIANT(
|
212 | 218 | access_path_label.size() >= 2,
|
213 | 219 | "Access path label must have length at least 2");
|
214 | 220 |
|
215 |
| - expr=dereference_exprt(expr); |
216 |
| - const struct_typet &struct_type=to_struct_type(ns.follow(expr.type())); |
217 |
| - |
218 |
| - /// First deal with any superclass identifiers |
219 |
| - while(access_path_label[1] == '@') |
| 221 | + if(access_path_label == "[]") |
220 | 222 | {
|
221 | 223 | DATA_INVARIANT(
|
222 |
| - access_path_label[0] == '.', |
223 |
| - "the label of an access path entry is malformed"); |
224 |
| - access_path_label = access_path_label.substr(1); |
225 |
| - INVARIANT( |
226 |
| - !has_prefix(access_path_label, "@lock") && |
| 224 | + std::prev(it)->label() == ".data", |
| 225 | + "Access path entry '[]' must be preceded by access path entry '.data'"); |
| 226 | + expr = dereference_exprt( |
| 227 | + plus_exprt( |
| 228 | + expr, side_effect_expr_nondett(java_int_type()), expr.type())); |
| 229 | + } |
| 230 | + else |
| 231 | + { |
| 232 | + expr=dereference_exprt(expr); |
| 233 | + const struct_typet &struct_type=to_struct_type(ns.follow(expr.type())); |
| 234 | + |
| 235 | + /// First deal with any superclass identifiers |
| 236 | + while(access_path_label[1]=='@') |
| 237 | + { |
| 238 | + DATA_INVARIANT( |
| 239 | + access_path_label[0]=='.', |
| 240 | + "the label of an access path entry is malformed"); |
| 241 | + access_path_label=access_path_label.substr(1); |
| 242 | + INVARIANT( |
| 243 | + !has_prefix(access_path_label, "@lock") && |
227 | 244 | !has_prefix(access_path_label, "@class_identifier"),
|
228 |
| - "Special fields @lock and @class_identifier should not be " |
229 |
| - "appearing in function summary"); |
| 245 | + "Special fields @lock and @class_identifier should not be " |
| 246 | + "appearing in function summary"); |
| 247 | + |
| 248 | + const auto expr_components=struct_type.components(); |
| 249 | + DATA_INVARIANT( |
| 250 | + !expr_components.empty(), |
| 251 | + "Cannot follow access path if expression has no components"); |
| 252 | + const auto &superclass_component=expr_components[0]; |
| 253 | + const std::string &superclass_name= |
| 254 | + id2string(superclass_component.get_name()); |
| 255 | + DATA_INVARIANT( |
| 256 | + has_prefix(access_path_label, superclass_name), |
| 257 | + "Access path label starting with @ must be followed by superclass " |
| 258 | + "name"); |
| 259 | + expr=member_exprt(expr, superclass_component); |
| 260 | + access_path_label=access_path_label.substr(superclass_name.size()); |
| 261 | + } |
230 | 262 |
|
231 |
| - const auto expr_components = struct_type.components(); |
| 263 | + /// Now we are just left with a field name |
232 | 264 | DATA_INVARIANT(
|
233 |
| - !expr_components.empty(), |
234 |
| - "Cannot follow access path if expression has no components"); |
235 |
| - const auto &superclass_component = expr_components[0]; |
236 |
| - const std::string &superclass_name = |
237 |
| - id2string(superclass_component.get_name()); |
238 |
| - DATA_INVARIANT( |
239 |
| - has_prefix(access_path_label, superclass_name), |
240 |
| - "Access path label starting with @ must be followed by superclass " |
241 |
| - "name"); |
242 |
| - expr = member_exprt(expr, superclass_component); |
243 |
| - access_path_label = access_path_label.substr(superclass_name.size()); |
| 265 | + access_path_label[0]=='.', |
| 266 | + "the label of an access path entry is malformed"); |
| 267 | + access_path_label=access_path_label.substr(1); |
| 268 | + auto &component=struct_type.get_component(access_path_label); |
| 269 | + INVARIANT( |
| 270 | + component.get_name()!=ID_nil, "Could not find field from access path"); |
| 271 | + expr=member_exprt(expr, component); |
244 | 272 | }
|
245 |
| - |
246 |
| - /// Now we are just left with a field name |
247 |
| - DATA_INVARIANT( |
248 |
| - access_path_label[0] == '.', |
249 |
| - "the label of an access path entry is malformed"); |
250 |
| - access_path_label = access_path_label.substr(1); |
251 |
| - auto &component = struct_type.get_component(access_path_label); |
252 |
| - INVARIANT( |
253 |
| - component.get_name() != ID_nil, "Could not find field from access path"); |
254 |
| - expr = member_exprt(expr, component); |
255 | 273 | }
|
256 | 274 |
|
257 | 275 | return expr;
|
|
0 commit comments