Skip to content

Commit b2d3d61

Browse files
committed
Search static fields inherited from interfaces
Previously we assumed that static fields, like regular fields, could only be inherited from ordinary classes, but in fact they can also come from interfaces. We therefore augment resolve-inherited-component to optionally search in all ancestors including interfaces, and use that facility when searching for inherited static fields.
1 parent 045ac05 commit b2d3d61

8 files changed

+40
-15
lines changed

src/goto-programs/remove_virtual_functions.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,11 @@ void remove_virtual_functionst::get_functions(
390390
const function_call_resolvert resolve_function_call =
391391
[&get_virtual_call_target](
392392
const irep_idt &class_id, const irep_idt &function_name) {
393-
return get_virtual_call_target(class_id, function_name);
393+
return get_virtual_call_target(class_id, function_name, false);
394394
};
395395

396396
const resolve_inherited_componentt::inherited_componentt
397-
&resolved_call = get_virtual_call_target(class_id, function_name);
397+
&resolved_call = get_virtual_call_target(class_id, function_name, false);
398398

399399
dispatch_table_entryt root_function;
400400

src/goto-programs/resolve_inherited_component.cpp

+21-6
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,25 @@ resolve_inherited_componentt::resolve_inherited_componentt(
4040
/// \param class_id: The name of the class the function is being called on
4141
/// \param component_name: The base name of the component (i.e. without the
4242
/// class specifier)
43+
/// \param include_interfaces: If true, consider inheritence from interfaces
44+
/// (parent types other than the first listed)
4345
/// \return The concrete component that has been resolved
4446
resolve_inherited_componentt::inherited_componentt
4547
resolve_inherited_componentt::operator()(
46-
const irep_idt &class_id, const irep_idt &component_name)
48+
const irep_idt &class_id,
49+
const irep_idt &component_name,
50+
bool include_interfaces)
4751
{
4852
PRECONDITION(!class_id.empty());
4953
PRECONDITION(!component_name.empty());
5054

51-
irep_idt current_class=class_id;
52-
while(!current_class.empty())
55+
std::vector<irep_idt> classes_to_visit;
56+
classes_to_visit.push_back(class_id);
57+
while(!classes_to_visit.empty())
5358
{
59+
irep_idt current_class = classes_to_visit.back();
60+
classes_to_visit.pop_back();
61+
5462
const irep_idt &full_component_identifier=
5563
build_full_component_identifier(current_class, component_name);
5664

@@ -62,9 +70,16 @@ resolve_inherited_componentt::inherited_componentt
6270
const class_hierarchyt::idst &parents=
6371
class_hierarchy.class_map[current_class].parents;
6472

65-
if(parents.empty())
66-
break;
67-
current_class=parents.front();
73+
if(include_interfaces)
74+
{
75+
classes_to_visit.insert(
76+
classes_to_visit.end(), parents.begin(), parents.end());
77+
}
78+
else
79+
{
80+
if(!parents.empty())
81+
classes_to_visit.push_back(parents.front());
82+
}
6883
}
6984

7085
return inherited_componentt();

src/goto-programs/resolve_inherited_component.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ class resolve_inherited_componentt
5757
};
5858

5959
inherited_componentt operator()(
60-
const irep_idt &class_id, const irep_idt &component_name);
60+
const irep_idt &class_id,
61+
const irep_idt &component_name,
62+
bool include_interfaces);
6163

6264
static irep_idt build_full_component_identifier(
6365
const irep_idt &class_name, const irep_idt &component_name);

src/java_bytecode/ci_lazy_methods.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -570,7 +570,7 @@ irep_idt ci_lazy_methodst::get_virtual_method_target(
570570

571571
resolve_inherited_componentt call_resolver(symbol_table, class_hierarchy);
572572
const resolve_inherited_componentt::inherited_componentt resolved_call =
573-
call_resolver(classname, call_basename);
573+
call_resolver(classname, call_basename, false);
574574

575575
if(resolved_call.is_valid())
576576
return resolved_call.get_full_component_identifier();

src/java_bytecode/java_bytecode_convert_method.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -2817,7 +2817,8 @@ bool java_bytecode_convert_methodt::is_method_inherited(
28172817
methodid,
28182818
classname,
28192819
symbol_table,
2820-
class_hierarchy);
2820+
class_hierarchy,
2821+
false);
28212822
return inherited_method.is_valid();
28222823
}
28232824

src/java_bytecode/java_bytecode_language.cpp

+4-1
Original file line numberDiff line numberDiff line change
@@ -451,13 +451,16 @@ static void create_stub_global_symbols(
451451
INVARIANT(
452452
!class_id.empty(), "get/putstatic should specify a class");
453453

454+
// The final 'true' parameter here includes interfaces, as they can
455+
// define static fields.
454456
resolve_inherited_componentt::inherited_componentt referred_component =
455457
get_inherited_component(
456458
class_id,
457459
component,
458460
"java::" + id2string(parse_tree.parsed_class.name),
459461
symbol_table,
460-
class_hierarchy);
462+
class_hierarchy,
463+
true);
461464
if(!referred_component.is_valid())
462465
{
463466
// Create a new stub global on the first incomplete (stub) parent of

src/java_bytecode/java_utils.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -337,19 +337,22 @@ std::string pretty_print_java_type(const std::string &fqn_java_type)
337337
/// scoped components are visible from a particular use site.
338338
/// \param symbol_table: global symbol table.
339339
/// \param class_hierarchy: global class hierarchy.
340+
/// \param include_interfaces: if true, search for the given component in all
341+
/// ancestors including interfaces, rather than just parents.
340342
/// \return the concrete component referred to if any is found, or an invalid
341343
/// resolve_inherited_componentt::inherited_componentt otherwise.
342344
resolve_inherited_componentt::inherited_componentt get_inherited_component(
343345
const irep_idt &component_class_id,
344346
const irep_idt &component_name,
345347
const irep_idt &user_class_id,
346348
const symbol_tablet &symbol_table,
347-
const class_hierarchyt &class_hierarchy)
349+
const class_hierarchyt &class_hierarchy,
350+
bool include_interfaces)
348351
{
349352
resolve_inherited_componentt component_resolver(
350353
symbol_table, class_hierarchy);
351354
const resolve_inherited_componentt::inherited_componentt resolved_component =
352-
component_resolver(component_class_id, component_name);
355+
component_resolver(component_class_id, component_name, include_interfaces);
353356

354357
// resolved_component is a pair (class-name, component-name) found by walking
355358
// the chain of class inheritance (not interfaces!) and stopping on the first

src/java_bytecode/java_utils.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ resolve_inherited_componentt::inherited_componentt get_inherited_component(
103103
const irep_idt &component_name,
104104
const irep_idt &user_class_id,
105105
const symbol_tablet &symbol_table,
106-
const class_hierarchyt &class_hierarchy);
106+
const class_hierarchyt &class_hierarchy,
107+
bool include_interfaces);
107108

108109
#endif // CPROVER_JAVA_BYTECODE_JAVA_UTILS_H

0 commit comments

Comments
 (0)