@@ -420,6 +420,39 @@ static void create_stub_global_symbol(
420
420
!add_failed, " caller should have checked symbol not already in table" );
421
421
}
422
422
423
+ // / Find any incomplete ancestor of a given class
424
+ // / \param start_class_id: class to start searching from
425
+ // / \param symbol_table: global symbol table
426
+ // / \param class_hierarchy: global class hierarchy
427
+ // / \return first incomplete ancestor encountered,
428
+ // / including start_class_id itself.
429
+ static irep_idt get_any_incomplete_ancestor (
430
+ const irep_idt &start_class_id,
431
+ const symbol_tablet &symbol_table,
432
+ const class_hierarchyt &class_hierarchy)
433
+ {
434
+ // Depth-first search: return the first ancestor with ID_incomplete_class, or
435
+ // irep_idt() if none found.
436
+ std::vector<irep_idt> classes_to_check;
437
+ classes_to_check.push_back (start_class_id);
438
+
439
+ while (!classes_to_check.empty ())
440
+ {
441
+ irep_idt to_check = classes_to_check.back ();
442
+ classes_to_check.pop_back ();
443
+
444
+ if (symbol_table.lookup_ref (to_check).type .get_bool (ID_incomplete_class))
445
+ return to_check;
446
+
447
+ const class_hierarchyt::idst &parents =
448
+ class_hierarchy.class_map .at (to_check).parents ;
449
+ classes_to_check.insert (
450
+ classes_to_check.end (), parents.begin (), parents.end ());
451
+ }
452
+
453
+ INVARIANT (false , " input class id should have some incomplete ancestor" );
454
+ }
455
+
423
456
// / Search for getstatic and putstatic instructions in a class' bytecode and
424
457
// / create stub symbols for any static fields that aren't already in the symbol
425
458
// / table. The new symbols are null-initialised for reference-typed globals /
@@ -463,19 +496,12 @@ static void create_stub_global_symbols(
463
496
true );
464
497
if (!referred_component.is_valid ())
465
498
{
466
- // Create a new stub global on the first incomplete (stub) parent of
467
- // the class that was referred to:
468
- irep_idt add_to_class_id = class_id;
469
- while (!symbol_table.lookup_ref (add_to_class_id).type .get_bool (
470
- ID_incomplete_class))
471
- {
472
- const class_hierarchyt::idst &parents =
473
- class_hierarchy.class_map .at (add_to_class_id).parents ;
474
- INVARIANT (
475
- !parents.empty (),
476
- " unresolved global reference should come from incomplete class" );
477
- add_to_class_id = parents[0 ];
478
- }
499
+ // Create a new stub global on an arbitrary incomplete ancestor of the
500
+ // class that was referred to. This is just a guess, but we have no
501
+ // better information to go on.
502
+ irep_idt add_to_class_id =
503
+ get_any_incomplete_ancestor (
504
+ class_id, symbol_table, class_hierarchy);
479
505
480
506
irep_idt identifier =
481
507
id2string (add_to_class_id) + " ." + id2string (component);
0 commit comments