|
13 | 13 | #include "java_string_library_preprocess.h"
|
14 | 14 | #include "remove_exceptions.h"
|
15 | 15 |
|
| 16 | +#include <util/expr_iterator.h> |
16 | 17 | #include <util/suffix.h>
|
17 | 18 |
|
18 | 19 | #include <goto-programs/resolve_inherited_component.h>
|
@@ -52,6 +53,31 @@ ci_lazy_methodst::ci_lazy_methodst(
|
52 | 53 | class_hierarchy(symbol_table);
|
53 | 54 | }
|
54 | 55 |
|
| 56 | +/// Checks if an expression refers to any class literals (e.g. MyType.class) |
| 57 | +/// These are expressed as ldc instructions in Java bytecode, and as symbols |
| 58 | +/// of the form MyType@class_model in GOTO programs. |
| 59 | +/// \param expr: expression to check |
| 60 | +/// \return true if the expression or any of its subexpressions refer to a |
| 61 | +/// class |
| 62 | +static bool references_class_model(const exprt &expr) |
| 63 | +{ |
| 64 | + static const symbol_typet class_type("java::java.lang.Class"); |
| 65 | + |
| 66 | + for(auto it = expr.depth_begin(); it != expr.depth_end(); ++it) |
| 67 | + { |
| 68 | + if(can_cast_expr<symbol_exprt>(*it) && |
| 69 | + it->type() == class_type && |
| 70 | + has_suffix( |
| 71 | + id2string(to_symbol_expr(*it).get_identifier()), |
| 72 | + JAVA_CLASS_MODEL_SUFFIX)) |
| 73 | + { |
| 74 | + return true; |
| 75 | + } |
| 76 | + } |
| 77 | + |
| 78 | + return false; |
| 79 | +} |
| 80 | + |
55 | 81 | /// Uses a simple context-insensitive ('ci') analysis to determine which methods
|
56 | 82 | /// may be reachable from the main entry point. In brief, static methods are
|
57 | 83 | /// reachable if we find a callsite in another reachable site, while virtual
|
@@ -122,6 +148,7 @@ bool ci_lazy_methodst::operator()(
|
122 | 148 |
|
123 | 149 | std::unordered_set<irep_idt> methods_already_populated;
|
124 | 150 | std::unordered_set<exprt, irep_hash> virtual_function_calls;
|
| 151 | + bool class_initializer_seen = false; |
125 | 152 |
|
126 | 153 | bool any_new_classes = true;
|
127 | 154 | while(any_new_classes)
|
@@ -149,8 +176,19 @@ bool ci_lazy_methodst::operator()(
|
149 | 176 | // Couldn't convert this function
|
150 | 177 | continue;
|
151 | 178 | }
|
152 |
| - gather_virtual_callsites( |
153 |
| - symbol_table.lookup_ref(mname).value, virtual_function_calls); |
| 179 | + const exprt &method_body = symbol_table.lookup_ref(mname).value; |
| 180 | + |
| 181 | + gather_virtual_callsites(method_body, virtual_function_calls); |
| 182 | + |
| 183 | + if(!class_initializer_seen && references_class_model(method_body)) |
| 184 | + { |
| 185 | + class_initializer_seen = true; |
| 186 | + irep_idt initializer_signature = |
| 187 | + get_java_class_literal_initializer_signature(); |
| 188 | + if(symbol_table.has_symbol(initializer_signature)) |
| 189 | + methods_to_convert_later.insert(initializer_signature); |
| 190 | + } |
| 191 | + |
154 | 192 | any_new_methods=true;
|
155 | 193 | }
|
156 | 194 | }
|
|
0 commit comments