diff options
author | Alexandre Petit-Bianco <apbianco@cygnus.com> | 1999-08-22 18:38:07 +0000 |
---|---|---|
committer | Alexandre Petit-Bianco <apbianco@gcc.gnu.org> | 1999-08-22 11:38:07 -0700 |
commit | d77613be8b4729d32825609d5e95e055b236c53a (patch) | |
tree | 768c1eb1b46e0cf93bc35c2e49b5c1aeb3af6ad2 /gcc/java | |
parent | 9d9169deaa2a0835754ea0b957d452ffa9690fa7 (diff) | |
download | gcc-d77613be8b4729d32825609d5e95e055b236c53a.zip gcc-d77613be8b4729d32825609d5e95e055b236c53a.tar.gz gcc-d77613be8b4729d32825609d5e95e055b236c53a.tar.bz2 |
re GNATS gcj/30 (gcj not reporting unimplemented methods)
Sun Aug 22 11:07:41 1999 Alexandre Petit-Bianco <apbianco@cygnus.com>
* parse.y (check_method_redefinition): Changed leading comment.
(check_abstract_method_definitions): New function.
(java_check_abstract_method_definitions): New function.
(java_check_regular_methods): Call it.
(verify_constructor_super): Fixed indentation.
(lookup_method_invoke): Likewise.
(This fixes the Java net PR #30,
http://sourceware.cygnus.com/ml/java-prs/1999-q3/msg00034.html)
From-SVN: r28805
Diffstat (limited to 'gcc/java')
-rw-r--r-- | gcc/java/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/java/parse.c | 136 | ||||
-rw-r--r-- | gcc/java/parse.y | 136 |
3 files changed, 267 insertions, 14 deletions
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index de425bb..b44dae0 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,12 @@ +Sun Aug 22 11:07:41 1999 Alexandre Petit-Bianco <apbianco@cygnus.com> + + * parse.y (check_method_redefinition): Changed leading comment. + (check_abstract_method_definitions): New function. + (java_check_abstract_method_definitions): New function. + (java_check_regular_methods): Call it. + (verify_constructor_super): Fixed indentation. + (lookup_method_invoke): Likewise. + Thu Aug 19 10:26:18 1999 Alexandre Petit-Bianco <apbianco@cygnus.com> * parse.y (method_header): Return a null pointer if the current diff --git a/gcc/java/parse.c b/gcc/java/parse.c index 2c7cf88..ba242a2 100644 --- a/gcc/java/parse.c +++ b/gcc/java/parse.c @@ -7134,7 +7134,7 @@ java_get_real_method_name (method_decl) /* Track method being redefined inside the same class. As a side effect, set DECL_NAME to an IDENTIFIER (prior entering this - function it's a FWL, so we can track errors more accurately */ + function it's a FWL, so we can track errors more accurately.) */ static int check_method_redefinition (class, method) @@ -7170,9 +7170,126 @@ check_method_redefinition (class, method) return 0; } -/* Check all the methods of CLASS. Methods are first completed then - checked according to regular method existance rules. - If no constructor were encountered, then build its declaration. */ +static void +check_abstract_method_definitions (do_interface, class_decl, type) + int do_interface; + tree class_decl, type; +{ + tree class = TREE_TYPE (class_decl); + tree method, end_type; + + end_type = (do_interface ? object_type_node : type); + for (method = TYPE_METHODS (type); method; method = TREE_CHAIN (method)) + { + tree other_super, other_method, method_sig, method_name; + int found = 0; + + if (!METHOD_ABSTRACT (method) || METHOD_FINAL (method)) + continue; + + /* Now verify that somewhere in between TYPE and CLASS, + abstract method METHOD gets a non abstract definition + that is inherited by CLASS. */ + + method_sig = build_java_signature (TREE_TYPE (method)); + method_name = DECL_NAME (method); + if (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION) + method_name = EXPR_WFL_NODE (method_name); + + for (other_super = class; other_super != end_type; + other_super = CLASSTYPE_SUPER (other_super)) + { + for (other_method = TYPE_METHODS (other_super); other_method; + other_method = TREE_CHAIN (other_method)) + { + tree s = build_java_signature (TREE_TYPE (other_method)); + tree other_name = DECL_NAME (other_method); + + if (TREE_CODE (other_name) == EXPR_WITH_FILE_LOCATION) + other_name = EXPR_WFL_NODE (other_name); + if (!IS_CLINIT (other_method) + && !DECL_CONSTRUCTOR_P (other_method) + && method_name == other_name && method_sig == s) + { + found = 1; + break; + } + } + } + + /* Report that abstract METHOD didn't find an implementation + that CLASS can use. */ + if (!found) + { + char *t = strdup (lang_printable_name + (TREE_TYPE (TREE_TYPE (method)), 0)); + tree ccn = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))); + tree saved_wfl = NULL_TREE; + + if (TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION) + { + saved_wfl = DECL_NAME (method); + DECL_NAME (method) = EXPR_WFL_NODE (DECL_NAME (method)); + } + + parse_error_context + (lookup_cl (class_decl), + "Class `%s' doesn't define the abstract method `%s %s' from " + "%s `%s'. This method must be defined or %s `%s' must be " + "declared abstract", + IDENTIFIER_POINTER (DECL_NAME (class_decl)), + t, lang_printable_name (method, 0), + (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))) ? + "interface" : "class"), + IDENTIFIER_POINTER (ccn), + (CLASS_INTERFACE (class_decl) ? "interface" : "class"), + IDENTIFIER_POINTER (DECL_NAME (class_decl))); + + free (t); + + if (saved_wfl) + DECL_NAME (method) = saved_wfl; + } + } +} + +/* Check that CLASS_DECL somehoow implements all inherited abstract + methods. */ + +static void +java_check_abstract_method_definitions (class_decl) + tree class_decl; +{ + tree class = TREE_TYPE (class_decl); + tree super, vector; + int i; + + if (CLASS_ABSTRACT (class_decl)) + return; + + /* Check for inherited types */ + for (super = CLASSTYPE_SUPER (class); super != object_type_node; + super = CLASSTYPE_SUPER (super)) + { + if (!CLASS_ABSTRACT (TYPE_NAME (super))) + continue; + + check_abstract_method_definitions (0, class_decl, super); + } + + /* Check for implemented interfaces. */ + vector = TYPE_BINFO_BASETYPES (class); + for (i = 1; i < TREE_VEC_LENGTH (vector); i++) + { + super = BINFO_TYPE (TREE_VEC_ELT (vector, i)); + check_abstract_method_definitions (1, class_decl, super); + } +} + +/* Check all the methods of CLASS_DECL. Methods are first completed + then checked according to regular method existance rules. If no + constructor for CLASS_DECL were encountered, then build its + declaration. */ static void java_check_regular_methods (class_decl) @@ -7348,7 +7465,7 @@ java_check_regular_methods (class_decl) /* Don't forget eventual pending found and saved_found_wfl. Take into account that we might have exited because we saw an - aritifical method as the last entry. */ + artificial method as the last entry. */ if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) DECL_NAME (found) = saved_found_wfl; @@ -7356,6 +7473,10 @@ java_check_regular_methods (class_decl) if (!TYPE_NVIRTUALS (class)) TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); + /* Search for inherited abstract method not yet implemented in this + class. */ + java_check_abstract_method_definitions (class_decl); + if (!saw_constructor) { /* No constructor seen, we craft one, at line 0. Since this @@ -8692,7 +8813,8 @@ verify_constructor_super () for (mdecl = TYPE_METHODS (class); mdecl; mdecl = TREE_CHAIN (mdecl)) { if (DECL_CONSTRUCTOR_P (mdecl) - && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (mdecl))) == end_params_node) + && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (mdecl))) + == end_params_node) return 0; } } @@ -10027,7 +10149,7 @@ lookup_method_invoke (lc, cl, class, name, arg_list) parse_error_context (cl, "Can't find %s `%s(%s)' in class `%s'%s", (lc ? "constructor" : "method"), (lc ? - IDENTIFIER_POINTER(DECL_NAME (TYPE_NAME (class))) : + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class))) : IDENTIFIER_POINTER (name)), IDENTIFIER_POINTER (signature), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class))), diff --git a/gcc/java/parse.y b/gcc/java/parse.y index d62b277..06426ba 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -4547,7 +4547,7 @@ java_get_real_method_name (method_decl) /* Track method being redefined inside the same class. As a side effect, set DECL_NAME to an IDENTIFIER (prior entering this - function it's a FWL, so we can track errors more accurately */ + function it's a FWL, so we can track errors more accurately.) */ static int check_method_redefinition (class, method) @@ -4583,9 +4583,126 @@ check_method_redefinition (class, method) return 0; } -/* Check all the methods of CLASS. Methods are first completed then - checked according to regular method existance rules. - If no constructor were encountered, then build its declaration. */ +static void +check_abstract_method_definitions (do_interface, class_decl, type) + int do_interface; + tree class_decl, type; +{ + tree class = TREE_TYPE (class_decl); + tree method, end_type; + + end_type = (do_interface ? object_type_node : type); + for (method = TYPE_METHODS (type); method; method = TREE_CHAIN (method)) + { + tree other_super, other_method, method_sig, method_name; + int found = 0; + + if (!METHOD_ABSTRACT (method) || METHOD_FINAL (method)) + continue; + + /* Now verify that somewhere in between TYPE and CLASS, + abstract method METHOD gets a non abstract definition + that is inherited by CLASS. */ + + method_sig = build_java_signature (TREE_TYPE (method)); + method_name = DECL_NAME (method); + if (TREE_CODE (method_name) == EXPR_WITH_FILE_LOCATION) + method_name = EXPR_WFL_NODE (method_name); + + for (other_super = class; other_super != end_type; + other_super = CLASSTYPE_SUPER (other_super)) + { + for (other_method = TYPE_METHODS (other_super); other_method; + other_method = TREE_CHAIN (other_method)) + { + tree s = build_java_signature (TREE_TYPE (other_method)); + tree other_name = DECL_NAME (other_method); + + if (TREE_CODE (other_name) == EXPR_WITH_FILE_LOCATION) + other_name = EXPR_WFL_NODE (other_name); + if (!IS_CLINIT (other_method) + && !DECL_CONSTRUCTOR_P (other_method) + && method_name == other_name && method_sig == s) + { + found = 1; + break; + } + } + } + + /* Report that abstract METHOD didn't find an implementation + that CLASS can use. */ + if (!found) + { + char *t = strdup (lang_printable_name + (TREE_TYPE (TREE_TYPE (method)), 0)); + tree ccn = DECL_NAME (TYPE_NAME (DECL_CONTEXT (method))); + tree saved_wfl = NULL_TREE; + + if (TREE_CODE (DECL_NAME (method)) == EXPR_WITH_FILE_LOCATION) + { + saved_wfl = DECL_NAME (method); + DECL_NAME (method) = EXPR_WFL_NODE (DECL_NAME (method)); + } + + parse_error_context + (lookup_cl (class_decl), + "Class `%s' doesn't define the abstract method `%s %s' from " + "%s `%s'. This method must be defined or %s `%s' must be " + "declared abstract", + IDENTIFIER_POINTER (DECL_NAME (class_decl)), + t, lang_printable_name (method, 0), + (CLASS_INTERFACE (TYPE_NAME (DECL_CONTEXT (method))) ? + "interface" : "class"), + IDENTIFIER_POINTER (ccn), + (CLASS_INTERFACE (class_decl) ? "interface" : "class"), + IDENTIFIER_POINTER (DECL_NAME (class_decl))); + + free (t); + + if (saved_wfl) + DECL_NAME (method) = saved_wfl; + } + } +} + +/* Check that CLASS_DECL somehoow implements all inherited abstract + methods. */ + +static void +java_check_abstract_method_definitions (class_decl) + tree class_decl; +{ + tree class = TREE_TYPE (class_decl); + tree super, vector; + int i; + + if (CLASS_ABSTRACT (class_decl)) + return; + + /* Check for inherited types */ + for (super = CLASSTYPE_SUPER (class); super != object_type_node; + super = CLASSTYPE_SUPER (super)) + { + if (!CLASS_ABSTRACT (TYPE_NAME (super))) + continue; + + check_abstract_method_definitions (0, class_decl, super); + } + + /* Check for implemented interfaces. */ + vector = TYPE_BINFO_BASETYPES (class); + for (i = 1; i < TREE_VEC_LENGTH (vector); i++) + { + super = BINFO_TYPE (TREE_VEC_ELT (vector, i)); + check_abstract_method_definitions (1, class_decl, super); + } +} + +/* Check all the methods of CLASS_DECL. Methods are first completed + then checked according to regular method existance rules. If no + constructor for CLASS_DECL were encountered, then build its + declaration. */ static void java_check_regular_methods (class_decl) @@ -4761,7 +4878,7 @@ java_check_regular_methods (class_decl) /* Don't forget eventual pending found and saved_found_wfl. Take into account that we might have exited because we saw an - aritifical method as the last entry. */ + artificial method as the last entry. */ if (found && !DECL_ARTIFICIAL (found) && saved_found_wfl) DECL_NAME (found) = saved_found_wfl; @@ -4769,6 +4886,10 @@ java_check_regular_methods (class_decl) if (!TYPE_NVIRTUALS (class)) TYPE_METHODS (class) = nreverse (TYPE_METHODS (class)); + /* Search for inherited abstract method not yet implemented in this + class. */ + java_check_abstract_method_definitions (class_decl); + if (!saw_constructor) { /* No constructor seen, we craft one, at line 0. Since this @@ -6105,7 +6226,8 @@ verify_constructor_super () for (mdecl = TYPE_METHODS (class); mdecl; mdecl = TREE_CHAIN (mdecl)) { if (DECL_CONSTRUCTOR_P (mdecl) - && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (mdecl))) == end_params_node) + && TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (mdecl))) + == end_params_node) return 0; } } @@ -7440,7 +7562,7 @@ lookup_method_invoke (lc, cl, class, name, arg_list) parse_error_context (cl, "Can't find %s `%s(%s)' in class `%s'%s", (lc ? "constructor" : "method"), (lc ? - IDENTIFIER_POINTER(DECL_NAME (TYPE_NAME (class))) : + IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class))) : IDENTIFIER_POINTER (name)), IDENTIFIER_POINTER (signature), IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (class))), |