+/* Check to make sure that all the methods in all the interfaces
+ implemented by CLASS_DECL are compatible with the concrete
+ implementations available in CHECK_CLASS_DECL. */
+static void
+check_interface_throws_clauses (tree check_class_decl, tree class_decl)
+{
+ for (; class_decl != NULL_TREE; class_decl = CLASSTYPE_SUPER (class_decl))
+ {
+ int i;
+
+ if (! CLASS_LOADED_P (class_decl))
+ {
+ if (CLASS_FROM_SOURCE_P (class_decl))
+ safe_layout_class (class_decl);
+ else
+ load_class (class_decl, 1);
+ }
+
+ for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (class_decl)) - 1; i > 0; --i)
+ {
+ tree interface
+ = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (class_decl), i));
+ tree iface_method;
+
+ for (iface_method = TYPE_METHODS (interface);
+ iface_method != NULL_TREE;
+ iface_method = TREE_CHAIN (iface_method))
+ {
+ tree sig, method;
+
+ /* First look for a concrete method implemented or
+ inherited by this class. No need to search
+ interfaces here, since we're already looking through
+ all of them. */
+ sig = build_java_argument_signature (TREE_TYPE (iface_method));
+ method
+ = lookup_argument_method_generic (check_class_decl,
+ DECL_NAME (iface_method),
+ sig, SEARCH_VISIBLE);
+ /* If we don't find an implementation, that is ok. Any
+ potential errors from that are diagnosed elsewhere.
+ Also, multiple inheritance with conflicting throws
+ clauses is fine in the absence of a concrete
+ implementation. */
+ if (method != NULL_TREE && !METHOD_ABSTRACT (method)
+ && !METHOD_INVISIBLE (iface_method))
+ {
+ tree method_wfl = DECL_FUNCTION_WFL (method);
+ check_throws_clauses (method, method_wfl, iface_method);
+ }
+ }
+
+ /* Now check superinterfaces. */
+ check_interface_throws_clauses (check_class_decl, interface);
+ }
+ }
+}
+
+/* Check throws clauses of a method against the clauses of all the
+ methods it overrides. We do this by searching up the class
+ hierarchy, examining all matching accessible methods. */
+static void
+check_concrete_throws_clauses (tree class, tree self_method,
+ tree name, tree signature)
+{
+ tree method = lookup_argument_method_generic (class, name, signature,
+ SEARCH_SUPER | SEARCH_VISIBLE);
+ while (method != NULL_TREE)
+ {
+ if (! METHOD_INVISIBLE (method) && hack_is_accessible_p (method, class))
+ check_throws_clauses (self_method, DECL_FUNCTION_WFL (self_method),
+ method);
+
+ method = lookup_argument_method_generic (DECL_CONTEXT (method),
+ name, signature,
+ SEARCH_SUPER | SEARCH_VISIBLE);
+ }
+}