@@ -325,3 +325,82 @@ std::string pretty_print_java_type(const std::string &fqn_java_type)
325
325
result = result.substr (java_lang_string.length ());
326
326
return result;
327
327
}
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