@@ -122,46 +122,88 @@ 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 , virtual_function_calls);
154
+ any_new_methods = true ;
148
155
}
149
- gather_virtual_callsites (
150
- symbol_table.lookup_ref (mname).value , virtual_function_calls);
151
- any_new_methods=true ;
152
156
}
153
- }
154
157
155
- // Given the object types we now know may be created, populate more
156
- // possible virtual function call targets:
158
+ // Given the object types we now know may be created, populate more
159
+ // possible virtual function call targets:
157
160
158
- debug () << " CI lazy methods: add virtual method targets ("
159
- << virtual_function_calls.size () << " callsites)" << eom;
161
+ debug () << " CI lazy methods: add virtual method targets ("
162
+ << virtual_function_calls.size () << " callsites)" << eom;
160
163
161
- for (const exprt &function : virtual_function_calls)
164
+ for (const exprt &function : virtual_function_calls)
165
+ {
166
+ get_virtual_method_targets (
167
+ function,
168
+ instantiated_classes,
169
+ methods_to_convert_later,
170
+ symbol_table);
171
+ }
172
+ }
173
+
174
+ any_new_classes = false ;
175
+
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)
162
179
{
180
+ id_sett candidate_target_methods;
163
181
get_virtual_method_targets (
164
- 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
+ }
165
207
}
166
208
}
167
209
0 commit comments