@@ -390,12 +390,17 @@ static void generate_constant_global_variables(
390
390
// / \param symbol_basename: new symbol basename
391
391
// / \param symbol_type: new symbol type
392
392
// / \param class_id: class id that directly encloses this static field
393
+ // / \param force_nondet_init: if true, always leave the symbol's value nil so it
394
+ // / gets nondet initialised during __CPROVER_initialize. Otherwise, pointer-
395
+ // / typed globals are initialised null and we expect a synthetic clinit method
396
+ // / to be created later.
393
397
static void create_stub_global_symbol (
394
398
symbol_table_baset &symbol_table,
395
399
const irep_idt &symbol_id,
396
400
const irep_idt &symbol_basename,
397
401
const typet &symbol_type,
398
- const irep_idt &class_id)
402
+ const irep_idt &class_id,
403
+ bool force_nondet_init)
399
404
{
400
405
symbolt new_symbol;
401
406
new_symbol.is_static_lifetime = true ;
@@ -415,7 +420,7 @@ static void create_stub_global_symbol(
415
420
// If pointer-typed, initialise to null and a static initialiser will be
416
421
// created to initialise on first reference. If primitive-typed, specify
417
422
// nondeterministic initialisation by setting a nil value.
418
- if (symbol_type.id () == ID_pointer)
423
+ if (symbol_type.id () == ID_pointer && !force_nondet_init )
419
424
new_symbol.value = null_pointer_exprt (to_pointer_type (symbol_type));
420
425
else
421
426
new_symbol.value .make_nil ();
@@ -454,7 +459,7 @@ static irep_idt get_any_incomplete_ancestor(
454
459
classes_to_check.end (), parents.begin (), parents.end ());
455
460
}
456
461
457
- INVARIANT ( false , " input class id should have some incomplete ancestor " );
462
+ return irep_idt ( );
458
463
}
459
464
460
465
// / Search for getstatic and putstatic instructions in a class' bytecode and
@@ -464,10 +469,13 @@ static irep_idt get_any_incomplete_ancestor(
464
469
// / \param parse_tree: class bytecode
465
470
// / \param symbol_table: symbol table; may gain new symbols
466
471
// / \param class_hierarchy: global class hierarchy
472
+ // / \param log: message handler used to log warnings when stub static fields are
473
+ // / found belonging to non-stub classes.
467
474
static void create_stub_global_symbols (
468
475
const java_bytecode_parse_treet &parse_tree,
469
476
symbol_table_baset &symbol_table,
470
- const class_hierarchyt &class_hierarchy)
477
+ const class_hierarchyt &class_hierarchy,
478
+ messaget &log)
471
479
{
472
480
namespacet ns (symbol_table);
473
481
for (const auto &method : parse_tree.parsed_class .methods )
@@ -507,6 +515,28 @@ static void create_stub_global_symbols(
507
515
get_any_incomplete_ancestor (
508
516
class_id, symbol_table, class_hierarchy);
509
517
518
+ // If there are no incomplete ancestors to ascribe the missing field
519
+ // to, we must have an incomplete model of a class or simply a
520
+ // version mismatch of some kind. Normally this would be an error, but
521
+ // our models library currently triggers this error in some cases
522
+ // (notably java.lang.System, which is missing System.in/out/err).
523
+ // Therefore for this case we ascribe the missing field to the class
524
+ // it was directly referenced from, and fall back to initialising the
525
+ // field in __CPROVER_initialize, rather than try to create or augment
526
+ // a clinit method for a non-stub class.
527
+
528
+ bool no_incomplete_ancestors = add_to_class_id.empty ();
529
+ if (no_incomplete_ancestors)
530
+ {
531
+ add_to_class_id = class_id;
532
+
533
+ // TODO forbid this again once the models library has been checked
534
+ // for missing static fields.
535
+ log .warning () << " Stub static field " << component << " found for "
536
+ << " non-stub type " << class_id << " . In future this "
537
+ << " will be a fatal error." << messaget::eom;
538
+ }
539
+
510
540
irep_idt identifier =
511
541
id2string (add_to_class_id) + " ." + id2string (component);
512
542
@@ -515,7 +545,8 @@ static void create_stub_global_symbols(
515
545
identifier,
516
546
component,
517
547
instruction.args [0 ].type (),
518
- add_to_class_id);
548
+ add_to_class_id,
549
+ no_incomplete_ancestors);
519
550
}
520
551
}
521
552
}
@@ -637,7 +668,7 @@ bool java_bytecode_languaget::typecheck(
637
668
for (const auto &c : java_class_loader.class_map )
638
669
{
639
670
create_stub_global_symbols (
640
- c.second , symbol_table_journal, class_hierarchy);
671
+ c.second , symbol_table_journal, class_hierarchy, * this );
641
672
}
642
673
643
674
stub_global_initializer_factory.create_stub_global_initializer_symbols (
0 commit comments