diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2b9bef58d883fb7196c0d74b15fd9fcbcf2a16df..3ea407057279f6498b83925f78425c117eeaf1bc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +2002-01-23 Zack Weinberg <zack@codesourcery.com> + + * Make-lang.in (parse.c): Adjust expected number of + shift-reduce conflicts. + (decl.o): Depend on diagnostic.h. + * decl.c: Include diagnostic.h. + (grokdeclarator): Check for null pointer. + (finish_function): Don't abort when + current_binding_level->parm_flag != 1, if errors have + occurred; throw away the statement tree and extra binding + levels, and continue. + * lex.c (note_list_got_semicolon): Check for null pointer. + * method.c (hack_identifier): Just return error_mark_node if + value is error_mark_node. + * parse.y (primary: TYPEID(type_id)): No need to use + TYPE_MAIN_VARIANT here. + (handler_seq): Accept an empty list of catch clauses and + generate a fake handler block to avoid later crashes. + (ansi_raise_identifier): Accept the error token too. + * semantics.c (begin_class_definition, + finish_class_definition): Check for error_mark_node. + 2002-01-23 Zack Weinberg <zack@codesourcery.com> * typeck2.c (friendly_abort): Delete definition. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index d848e3a5182a14e1b17bf2387702fe75cdb7e6ad..3b14ab181b3104191e131c4580d150096112129c 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -120,7 +120,7 @@ $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf $(srcdir)/cp/parse.h: $(srcdir)/cp/parse.c $(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y - @echo "Expect 34 shift/reduce conflicts and 58 reduce/reduce conflicts." + @echo "Expect 36 shift/reduce conflicts and 58 reduce/reduce conflicts." cd $(srcdir)/cp; $(BISON) $(BISONFLAGS) -d -o p$$$$.c parse.y ; \ grep '^#define[ ]*YYEMPTY' p$$$$.c >> p$$$$.h ; \ mv -f p$$$$.c parse.c ; mv -f p$$$$.h parse.h @@ -249,7 +249,7 @@ cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h langhooks-def.h \ c-common.h cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \ output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \ - cp/operators.def $(TM_P_H) tree-inline.h + cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \ output.h except.h toplev.h $(GGC_H) $(RTL_H) cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 35211135cf0fe319f04564b5717868c54218c4e9..0bb5dfd404cdd60ba9a7b5bd9330823a0ff6d56e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */ #include "tm_p.h" #include "target.h" #include "c-common.h" +#include "diagnostic.h" extern const struct attribute_spec *lang_attribute_table; @@ -10144,7 +10145,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) common. With no options, it is allowed. With -Wreturn-type, it is a warning. It is only an error with -pedantic-errors. */ is_main = (funcdef_flag - && MAIN_NAME_P (dname) + && dname && MAIN_NAME_P (dname) && ctype == NULL_TREE && in_namespace == NULL_TREE && current_namespace == global_namespace); @@ -14163,8 +14164,28 @@ finish_function (flags) /* This must come after expand_function_end because cleanups might have declarations (from inline functions) that need to go into this function's blocks. */ + + /* If the current binding level isn't the outermost binding level + for this function, either there is a bug, or we have experienced + syntax errors and the statement tree is malformed. */ if (current_binding_level->parm_flag != 1) - abort (); + { + /* Make sure we have already experienced errors. */ + if (errorcount == 0) + abort (); + + /* Throw away the broken statement tree and extra binding + levels. */ + DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE); + + while (current_binding_level->parm_flag != 1) + { + if (current_binding_level->parm_flag == 2) + pop_nested_class (); + else + poplevel (0, 0, 0); + } + } poplevel (1, 0, 1); /* Set up the named return value optimization, if we can. Here, we diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index b30c8171675d3ea76aa988eb36fc8cb8a3701837..0287f7040323e0fb8422b950d69d87302f4cb215 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -1026,7 +1026,7 @@ note_list_got_semicolon (declspecs) for (link = declspecs; link; link = TREE_CHAIN (link)) { tree type = TREE_VALUE (link); - if (TYPE_P (type)) + if (type && TYPE_P (type)) note_got_semicolon (type); } clear_anon_tags (); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 0848bd35a27155d58af7131fcf325f66bc307b46..b0cc63a5c0f0644183a57e9f44e28405d60a7e61 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -145,38 +145,7 @@ hack_identifier (value, name) tree type; if (value == error_mark_node) - { - if (current_class_name) - { - tree fields = lookup_fnfields (TYPE_BINFO (current_class_type), - name, 1); - if (fields == error_mark_node) - return error_mark_node; - if (fields) - { - tree fndecl; - - fndecl = TREE_VALUE (fields); - my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 251); - /* I could not trigger this code. MvL */ - abort (); -#ifdef DEAD - if (DECL_CHAIN (fndecl) == NULL_TREE) - { - warning ("methods cannot be converted to function pointers"); - return fndecl; - } - else - { - error ("ambiguous request for method pointer `%s'", - IDENTIFIER_POINTER (name)); - return error_mark_node; - } -#endif - } - } - return error_mark_node; - } + return error_mark_node; type = TREE_TYPE (value); if (TREE_CODE (value) == FIELD_DECL) diff --git a/gcc/cp/parse.y b/gcc/cp/parse.y index f6dba7ec4ceedcae53d159279ae5c9c03fc16f30..83a1cd020aa4d9247db58f0f6158f731c3aa38ce 100644 --- a/gcc/cp/parse.y +++ b/gcc/cp/parse.y @@ -1650,7 +1650,7 @@ primary: | TYPEID '(' type_id ')' { tree type = groktypename ($3.t); check_for_new_type ("typeid", $3); - $$ = get_typeid (TYPE_MAIN_VARIANT (type)); } + $$ = get_typeid (type); } | global_scope IDENTIFIER { $$ = do_scoped_id ($2, 1); } | global_scope template_id @@ -3505,6 +3505,15 @@ try_block: handler_seq: handler | handler_seq handler + | /* empty */ + { /* Generate a fake handler block to avoid later aborts. */ + tree fake_handler = begin_handler (); + finish_handler_parms (NULL_TREE, fake_handler); + finish_handler (fake_handler); + $<ttype>$ = fake_handler; + + error ("must have at least one catch per try block"); + } ; handler: @@ -3809,6 +3818,8 @@ ansi_raise_identifier: check_for_new_type ("exception specifier", $1); $$ = groktypename ($1.t); } + | error + { $$ = error_mark_node; } ; ansi_raise_identifiers: diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1f8d48164769082a40d222d710063d92ab7b8f1c..37729bfd9670c6b0a8a770460abfe7df3427dbb5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1669,6 +1669,9 @@ tree begin_class_definition (t) tree t; { + if (t == error_mark_node) + return error_mark_node; + /* Check the bases are accessible. */ decl_type_access_control (TYPE_NAME (t)); reset_type_access_control (); @@ -1878,6 +1881,9 @@ finish_class_definition (t, attributes, semi, pop_scope_p) int semi; int pop_scope_p; { + if (t == error_mark_node) + return error_mark_node; + /* finish_struct nukes this anyway; if finish_exception does too, then it can go. */ if (semi)