@@ -122,52 +122,92 @@ bool ci_lazy_methodst::operator()(
122
122
id_sett methods_already_populated;
123
123
std::unordered_set<exprt, irep_hash> virtual_function_calls;
124
124
125
- bool any_new_methods= true ;
126
- while (any_new_methods )
125
+ bool any_new_classes = true ;
126
+ while (any_new_classes )
127
127
{
128
- any_new_methods=false ;
129
- while (!methods_to_convert_later. empty () )
128
+ bool any_new_methods=true ;
129
+ while (any_new_methods )
130
130
{
131
- id_sett methods_to_convert;
132
- std::swap (methods_to_convert, methods_to_convert_later);
133
- for (const auto &mname : methods_to_convert)
131
+ any_new_methods=false ;
132
+ while (!methods_to_convert_later.empty ())
134
133
{
135
- if (!methods_already_populated.insert (mname).second )
136
- continue ;
137
- debug () << " CI lazy methods: elaborate " << mname << eom;
138
- if (
139
- method_converter (
140
- mname,
141
- // Note this wraps *references* to methods_to_convert_later &
142
- // instantiated_classes
143
- ci_lazy_methods_neededt (
144
- methods_to_convert_later, instantiated_classes, symbol_table)))
134
+ id_sett methods_to_convert;
135
+ std::swap (methods_to_convert, methods_to_convert_later);
136
+ for (const auto &mname : methods_to_convert)
145
137
{
146
- // Couldn't convert this function
147
- continue ;
138
+ if (!methods_already_populated.insert (mname).second )
139
+ continue ;
140
+ debug () << " CI lazy methods: elaborate " << mname << eom;
141
+ if (
142
+ method_converter (
143
+ mname,
144
+ // Note this wraps *references* to methods_to_convert_later &
145
+ // instantiated_classes
146
+ ci_lazy_methods_neededt (
147
+ methods_to_convert_later, instantiated_classes, symbol_table)))
148
+ {
149
+ // Couldn't convert this function
150
+ continue ;
151
+ }
152
+ gather_virtual_callsites (
153
+ symbol_table.lookup_ref (mname).value ,
154
+ virtual_function_calls);
155
+ any_new_methods=true ;
148
156
}
149
- gather_virtual_callsites (
150
- symbol_table.lookup_ref (mname).value ,
151
- virtual_function_calls);
152
- any_new_methods=true ;
153
157
}
154
- }
155
158
156
- // Given the object types we now know may be created, populate more
157
- // possible virtual function call targets:
159
+ // Given the object types we now know may be created, populate more
160
+ // possible virtual function call targets:
161
+
162
+ debug () << " CI lazy methods: add virtual method targets ("
163
+ << virtual_function_calls.size ()
164
+ << " callsites)"
165
+ << eom;
166
+
167
+ for (const exprt &function : virtual_function_calls)
168
+ {
169
+ get_virtual_method_targets (
170
+ function, instantiated_classes, methods_to_convert_later, symbol_table);
171
+ }
172
+ }
158
173
159
- debug () << " CI lazy methods: add virtual method targets ("
160
- << virtual_function_calls.size ()
161
- << " callsites)"
162
- << eom;
174
+ any_new_classes = false ;
163
175
164
- for (const exprt &function : virtual_function_calls)
176
+ // Find virtual callsites with no candidate targets, guess that the class
177
+ // must be instantiated, and create a stub method if needed
178
+ for (const exprt &virtual_function_call : virtual_function_calls)
165
179
{
180
+ id_sett candidate_target_methods;
166
181
get_virtual_method_targets (
167
- function, instantiated_classes, methods_to_convert_later, symbol_table);
182
+ virtual_function_call,
183
+ instantiated_classes,
184
+ candidate_target_methods,
185
+ symbol_table);
186
+
187
+ if (candidate_target_methods.empty ())
188
+ {
189
+ any_new_classes = true ;
190
+
191
+ // Add the call class to instantiated_classes and assert that it
192
+ // didn't already exist
193
+ const irep_idt &call_class = virtual_function_call.get (ID_C_class);
194
+ auto ret_class = instantiated_classes.insert (call_class);
195
+ CHECK_RETURN (ret_class.second );
196
+
197
+ // Check that `get_virtual_method_target` returns a method now
198
+ const irep_idt &call_basename =
199
+ virtual_function_call.get (ID_component_name);
200
+ const irep_idt method_name = get_virtual_method_target (
201
+ instantiated_classes, call_basename, call_class, symbol_table);
202
+ CHECK_RETURN (!method_name.empty ());
203
+
204
+ // Add what it returns to methods_to_convert_later
205
+ methods_to_convert_later.insert (method_name);
206
+ }
168
207
}
169
208
}
170
209
210
+
171
211
// Remove symbols for methods that were declared but never used:
172
212
symbol_tablet keep_symbols;
173
213
// Manually keep @inflight_exception, as it is unused at this stage
0 commit comments