Skip to content

Commit 06553e7

Browse files
Uses containing class to determine accessibility
1 parent d334ae5 commit 06553e7

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,3 +1154,60 @@ void mark_java_implicitly_generic_class_type(
11541154
}
11551155
}
11561156
}
1157+
1158+
/// If access1 is stricter than access2, returns true, otherwise returns false.
1159+
/// Assumed order of strictness:
1160+
/// private, default (package_private), protected, public
1161+
bool compare_access(irep_idt access1, irep_idt access2)
1162+
{
1163+
if(access1 == access2)
1164+
return false;
1165+
if(access1 == ID_private)
1166+
return true;
1167+
if(access1 == ID_default && access2 != ID_private)
1168+
return true;
1169+
if(access1 == ID_protected && access2 == ID_public)
1170+
return true;
1171+
return false;
1172+
}
1173+
1174+
/// Inner class accessibility depends not only on the inner class' access
1175+
/// modifier, but the access modifiers of its containing classes. This checks
1176+
/// all of the containing classes of an inner class and sets the access of the
1177+
/// inner class to the strictest of its containing classes. For example, for a
1178+
/// deeply nested structure Outer.Middle.Inner with access modifiers public,
1179+
/// private, public, respectively, the access of Inner should be private
1180+
/// (not public) because one of its containing classes has private access.
1181+
/// \param inner_class_name
1182+
/// \param symbol_table
1183+
void determine_inner_class_accessibility(
1184+
const irep_idt &inner_class_name,
1185+
symbol_tablet &symbol_table)
1186+
{
1187+
const std::string qualified_inner_class_name =
1188+
"java::" + id2string(inner_class_name);
1189+
PRECONDITION(symbol_table.has_symbol(qualified_inner_class_name));
1190+
symbolt &inner_class_symbol =
1191+
symbol_table.get_writeable_ref(qualified_inner_class_name);
1192+
java_class_typet &inner_class_type =
1193+
to_java_class_type(inner_class_symbol.type);
1194+
1195+
if(!inner_class_type.get_is_inner_class())
1196+
return;
1197+
if(inner_class_type.get_containing_class().empty())
1198+
return;
1199+
const std::string qualified_containing_class_name =
1200+
"java::" + id2string(inner_class_type.get_containing_class());
1201+
PRECONDITION(symbol_table.has_symbol(qualified_containing_class_name));
1202+
symbolt &containing_class_symbol =
1203+
symbol_table.get_writeable_ref(qualified_containing_class_name);
1204+
java_class_typet &containing_class_type =
1205+
to_java_class_type(containing_class_symbol.type);
1206+
1207+
if(
1208+
compare_access(
1209+
containing_class_type.get_access(), inner_class_type.get_access()))
1210+
{
1211+
inner_class_type.set_access(containing_class_type.get_access());
1212+
}
1213+
}

jbmc/src/java_bytecode/java_bytecode_convert_class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ void mark_java_implicitly_generic_class_type(
4141
const irep_idt &class_name,
4242
symbol_tablet &symbol_table);
4343

44+
void determine_inner_class_accessibility(
45+
const irep_idt &class_name,
46+
symbol_tablet &symbol_table);
47+
4448
/// An exception that is raised checking whether a class is implicitly
4549
/// generic if a symbol for an outer class is missing
4650
class missing_outer_class_symbol_exceptiont : public std::logic_error

jbmc/src/java_bytecode/java_bytecode_language.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,16 @@ bool java_bytecode_languaget::typecheck(
677677
}
678678
}
679679

680+
// Determine inner class accessibility by taking the most strict of access
681+
// modifiers of all of the containing classes
682+
for(const auto &c : java_class_loader.get_class_with_overlays_map())
683+
{
684+
if(c.second.front().parsed_class.containing_class.empty())
685+
continue;
686+
determine_inner_class_accessibility(
687+
c.second.front().parsed_class.name, symbol_table);
688+
}
689+
680690
// Infer fields on opaque types based on the method instructions just loaded.
681691
// For example, if we don't have bytecode for field x of class A, but we can
682692
// see an int-typed getfield instruction referring to it, add that field now.

0 commit comments

Comments
 (0)