@@ -325,3 +325,82 @@ std::string pretty_print_java_type(const std::string &fqn_java_type)
325325 result = result.substr (java_lang_string.length ());
326326 return result;
327327}
328+
329+ // / Finds an inherited component (method or field), taking component visibility
330+ // / into account.
331+ // / \param component_class_id: class to start searching from. For example, if
332+ // / trying to resolve a reference to A.b, component_class_id is "A".
333+ // / \param component_name: component basename to search for. If searching for
334+ // / A.b, this is "b".
335+ // / \param user_class_id: class identifier making reference to the sought
336+ // / component. The user class is relevant when determining whether package-
337+ // / scoped components are visible from a particular use site.
338+ // / \param symbol_table: global symbol table.
339+ // / \return the concrete component referred to if any is found, or an invalid
340+ // / resolve_inherited_componentt::inherited_componentt otherwise.
341+ resolve_inherited_componentt::inherited_componentt get_inherited_component (
342+ const irep_idt &component_class_id,
343+ const irep_idt &component_name,
344+ const irep_idt &user_class_id,
345+ const symbol_tablet &symbol_table)
346+ {
347+ resolve_inherited_componentt component_resolver (symbol_table);
348+ const resolve_inherited_componentt::inherited_componentt resolved_component =
349+ component_resolver (component_class_id, component_name);
350+
351+ // resolved_component is a pair (class-name, component-name) found by walking
352+ // the chain of class inheritance (not interfaces!) and stopping on the first
353+ // class that contains a component of equal name and type to `component_name`
354+
355+ if (resolved_component.is_valid ())
356+ {
357+ // Directly defined on the class referred to?
358+ if (component_class_id == resolved_component.get_class_identifier ())
359+ return resolved_component;
360+
361+ // No, may be inherited from some parent class; check it is visible:
362+ const symbolt &component_symbol=
363+ *symbol_table.lookup (resolved_component.get_full_component_identifier ());
364+
365+ const auto &access=component_symbol.type .get (ID_access);
366+ if (access==ID_public || access==ID_protected)
367+ {
368+ // since the component is public, it is inherited
369+ return resolved_component;
370+ }
371+
372+ // components with the default access modifier are only
373+ // accessible within the same package.
374+ if (access==ID_default)
375+ {
376+ const std::string &class_package=
377+ java_class_to_package (id2string (component_class_id));
378+ const std::string &component_package=
379+ java_class_to_package (
380+ id2string (
381+ resolved_component.get_class_identifier ()));
382+ if (component_package == class_package)
383+ return resolved_component;
384+ else
385+ return resolve_inherited_componentt::inherited_componentt ();
386+ }
387+
388+ if (access==ID_private)
389+ {
390+ // We return not-found because the component found by the
391+ // component_resolver above proves that `component_name` cannot be
392+ // inherited (assuming that the original Java code compiles). This is
393+ // because, as we walk the inheritance chain for `classname` from Object
394+ // to `classname`, a component can only become "more accessible". So, if
395+ // the last occurrence is private, all others before must be private as
396+ // well, and none is inherited in `classname`.
397+ return resolve_inherited_componentt::inherited_componentt ();
398+ }
399+
400+ UNREACHABLE; // Unexpected access modifier
401+ }
402+ else
403+ {
404+ return resolve_inherited_componentt::inherited_componentt ();
405+ }
406+ }
0 commit comments