|
| 1 | +/*******************************************************************\ |
| 2 | +
|
| 3 | +Module: Assignments to values specified in JSON files |
| 4 | +
|
| 5 | +Author: Diffblue Ltd. |
| 6 | +
|
| 7 | +\*******************************************************************/ |
| 8 | + |
| 9 | +/// \file |
| 10 | + |
| 11 | +#ifndef CPROVER_JAVA_BYTECODE_ASSIGNMENTS_FROM_JSON_H |
| 12 | +#define CPROVER_JAVA_BYTECODE_ASSIGNMENTS_FROM_JSON_H |
| 13 | + |
| 14 | +#include <util/std_code.h> |
| 15 | + |
| 16 | +/// Information to store when several references point to the same Java object. |
| 17 | +struct object_creation_referencet |
| 18 | +{ |
| 19 | + /// Expression for the symbol that stores the value that may be reference |
| 20 | + /// equal to other values. |
| 21 | + exprt expr; |
| 22 | + |
| 23 | + /// If `symbol` is an array, this expression stores its length. |
| 24 | + optionalt<symbol_exprt> array_length; |
| 25 | +}; |
| 26 | + |
| 27 | +class jsont; |
| 28 | +class symbol_table_baset; |
| 29 | +class ci_lazy_methods_neededt; |
| 30 | + |
| 31 | +/// Given an expression \p expr representing a Java object or primitive and a |
| 32 | +/// JSON representation \p json of the value of a Java object or primitive of a |
| 33 | +/// compatible type, adds statements to \p block to assign \p expr to the |
| 34 | +/// deterministic value specified by \p json. |
| 35 | +/// The expected format of the JSON representation is mostly the same as that |
| 36 | +/// of the json-io serialization library (https://github.com/jdereg/json-io) if |
| 37 | +/// run with the following options, as of version 4.10.1: |
| 38 | +/// - A type name map with identity mappings such as |
| 39 | +/// `("java.lang.Boolean", "java.lang.Boolean")` for all primitive wrapper |
| 40 | +/// types, java.lang.Class, java.lang.String and java.util.Date. That is, we |
| 41 | +/// are not using the json-io default shorthands for those types. |
| 42 | +/// - `WRITE_LONGS_AS_STRINGS` should be set to `true` to avoid a loss of |
| 43 | +/// precision when representing longs. |
| 44 | +/// |
| 45 | +/// Some examples of json-io representations that may not be obvious include: |
| 46 | +/// - The representation of a Java object generally may or may not contain a |
| 47 | +/// `"@type"` key. The value corresponding to such a key specifies the runtime |
| 48 | +/// type of the object (or the boxed type if the object is primitive). If no |
| 49 | +/// `"@type"` key is present, it is assumed that the runtime type is the same |
| 50 | +/// as the compile-time type. Most reference-typed objects are represented as |
| 51 | +/// JSON objects (i.e. key-value maps) either way, so the `"@type"` key is |
| 52 | +/// just an additional key in the map. However, primitive types, arrays and |
| 53 | +/// string types without a `"@type"` key are not represented as JSON objects. |
| 54 | +/// For example, "untyped" ints are just represented as e.g. 1234, i.e. a JSON |
| 55 | +/// number. The "typed" version of this int then becomes |
| 56 | +/// `{"@type":"java.lang.Integer","value":1234}`, i.e. a JSON object, with the |
| 57 | +/// original ("untyped") JSON number stored in the "value" entry. For arrays, |
| 58 | +/// the corresponding key is called "@items", not "value". Typed versions of |
| 59 | +/// primitive types are probably not necessary, but json-io will sometimes |
| 60 | +/// produce such values, which is why we support both typed and untyped |
| 61 | +/// versions. |
| 62 | +/// - The way we deal with reference-equal objects is that they all get assigned |
| 63 | +/// the same ID, and exactly one of them will have an `{"@id": some_ID}` |
| 64 | +/// entry, in addition to its usual representation. All the other objects with |
| 65 | +/// this ID are represented simply as `{"@ref": some_ID}`, with no further |
| 66 | +/// entries. |
| 67 | +/// |
| 68 | +/// The above rule has the following exceptions: |
| 69 | +/// - It seems that strings are always printed in "primitive" representation by |
| 70 | +/// json-io, i.e.\ they are always JSON strings, and never JSON objects with |
| 71 | +/// a `@type` key. For cases where we don't know that an expression has a |
| 72 | +/// string type (e.g.\ if its type is generic and specialized to |
| 73 | +/// java.lang.String), we need to sometimes represent strings as JSON objects |
| 74 | +/// with a `@type` key. In this case, the content of the string will be the |
| 75 | +/// value associated with a `value` key (similarly to StringBuilder in |
| 76 | +/// json-io). See \ref get_untyped_string. |
| 77 | +/// - json-io does not include the `ordinal` field of enums in its |
| 78 | +/// representation, but our algorithm depends on it being present. It may be |
| 79 | +/// possible to rewrite parts of it to set the ordinal depending on the order |
| 80 | +/// of elements seen in the `$VALUES` array, but it would generally make |
| 81 | +/// things more complicated. |
| 82 | +/// |
| 83 | +/// For examples of JSON representations of objects, see the regression tests |
| 84 | +/// for this feature in |
| 85 | +/// jbmc/regression/jbmc/deterministic_assignments_json. |
| 86 | +/// |
| 87 | +/// Known limitations: |
| 88 | +/// - If two reference-equal objects are defined in the same function, they are |
| 89 | +/// correctly assigned the same value. |
| 90 | +/// However, the case where they are defined in two different functions is not |
| 91 | +/// supported. The object that is stored as a `{"@ref":1}` or similar will |
| 92 | +/// generally either point to a freshly allocated symbol or an out-of-scope |
| 93 | +/// symbol. The `{"@id":1}` (or similar) object may be assigned correctly, or |
| 94 | +/// it may point to an out-of-scope symbol. This is because the symbol for the |
| 95 | +/// shared value is currently allocated dynamically. To fix this limitation, |
| 96 | +/// static allocation would have to be used instead, together with a static |
| 97 | +/// boolean to keep track of whether or not the symbol has been allocated |
| 98 | +/// already. |
| 99 | +/// - The special floating-point values NaN and positive/negative infinity are |
| 100 | +/// not supported. Note that in json-io 4.10.1, these are printed as "null". |
| 101 | +/// Future versions of json-io will support these values, and this function |
| 102 | +/// should be consistent with that if possible. |
| 103 | +/// - json-io prints \\uFFFF as a single character, which is not read correctly |
| 104 | +/// by the JSON parser. |
| 105 | +/// - Not all assignments have source locations, and those that do only link to |
| 106 | +/// a function, not a line number. |
| 107 | +/// |
| 108 | +/// For parameter documentation, see \ref det_creation_infot. |
| 109 | +void assign_from_json( |
| 110 | + const exprt &expr, |
| 111 | + const jsont &json, |
| 112 | + const irep_idt &function_id, |
| 113 | + code_blockt &block, |
| 114 | + symbol_table_baset &symbol_table, |
| 115 | + optionalt<ci_lazy_methods_neededt> &needed_lazy_methods, |
| 116 | + size_t max_user_array_length, |
| 117 | + std::unordered_map<std::string, object_creation_referencet> &references); |
| 118 | + |
| 119 | +#endif // CPROVER_JAVA_BYTECODE_ASSIGNMENTS_FROM_JSON_H |
0 commit comments