diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-common.c | 32 | ||||
-rw-r--r-- | gcc/c-common.h | 1 | ||||
-rw-r--r-- | gcc/c-parse.in | 23 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 37 | ||||
-rw-r--r-- | gcc/cp/parser.c | 551 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/mangle4.C | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/using5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/other/error2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/error3.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/error4.C | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/typename5.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/undefined1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/arg2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/ttp3.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/type1.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.other/crash32.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/defarg8.C | 6 |
19 files changed, 385 insertions, 321 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f43d14b..f933812 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2003-12-14 Mark Mitchell <mark@codesourcery.com> + + * c-common.h (c_parse_error): Declare it. + * c-common.c (c_parse_error): New function. + * c-parse.y (yyerror): Use it. + 2003-12-14 John David Anglin <dave.anglin@nrc-cnrc.gc.ca> PR target/13054 diff --git a/gcc/c-common.c b/gcc/c-common.c index acc1e44..4ba17e0 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -5893,4 +5893,36 @@ c_decl_uninit (tree t) return false; } +/* Issue the error given by MSGID, indicating that it occurred before + TOKEN, which had the associated VALUE. */ + +void +c_parse_error (const char *msgid, enum cpp_ttype token, tree value) +{ + const char *string = _(msgid); + + if (token == CPP_EOF) + error ("%s at end of input", string); + else if (token == CPP_CHAR || token == CPP_WCHAR) + { + unsigned int val = TREE_INT_CST_LOW (value); + const char *const ell = (token == CPP_CHAR) ? "" : "L"; + if (val <= UCHAR_MAX && ISGRAPH (val)) + error ("%s before %s'%c'", string, ell, val); + else + error ("%s before %s'\\x%x'", string, ell, val); + } + else if (token == CPP_STRING + || token == CPP_WSTRING) + error ("%s before string constant", string); + else if (token == CPP_NUMBER) + error ("%s before numeric constant", string); + else if (token == CPP_NAME) + error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value)); + else if (token < N_TTYPES) + error ("%s before '%s' token", string, cpp_type2name (token)); + else + error ("%s", string); +} + #include "gt-c-common.h" diff --git a/gcc/c-common.h b/gcc/c-common.h index ccfc779..326fe51 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -1330,6 +1330,7 @@ extern void c_stddef_cpp_builtins (void); extern void fe_file_change (const struct line_map *); extern int c_estimate_num_insns (tree decl); extern bool c_decl_uninit (tree t); +extern void c_parse_error (const char *, enum cpp_ttype, tree); /* The following have been moved here from c-tree.h, since they're needed in the ObjC++ world, too. What is more, stub-objc.c could use a few diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 320c781..b36ab06 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -3551,28 +3551,7 @@ init_reswords (void) static void yyerror (const char *msgid) { - const char *string = _(msgid); - - if (last_token == CPP_EOF) - error ("%s at end of input", string); - else if (last_token == CPP_CHAR || last_token == CPP_WCHAR) - { - unsigned int val = TREE_INT_CST_LOW (yylval.ttype); - const char *const ell = (last_token == CPP_CHAR) ? "" : "L"; - if (val <= UCHAR_MAX && ISGRAPH (val)) - error ("%s before %s'%c'", string, ell, val); - else - error ("%s before %s'\\x%x'", string, ell, val); - } - else if (last_token == CPP_STRING - || last_token == CPP_WSTRING) - error ("%s before string constant", string); - else if (last_token == CPP_NUMBER) - error ("%s before numeric constant", string); - else if (last_token == CPP_NAME) - error ("%s before \"%s\"", string, IDENTIFIER_POINTER (yylval.ttype)); - else - error ("%s before '%s' token", string, NAME(last_token)); + c_parse_error (msgid, last_token, yylval.ttype); } static int diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 31d16d2..732273e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,40 @@ +2003-12-14 Mark Mitchell <mark@codesourcery.com> + + PR c++/10779 + PR c++/12160 + * parser.c (struct cp_parser): Add in_template_argument_list_p. + (cp_parser_error): Use c_parse_error. + (cp_parser_name_lookup_error): New function. + (cp_parser_new): Initialize it. + (cp_parser_declarator): Add parenthesized_p parameter. + (cp_parser_nested_name_specifier_opt): Use + cp_parser_name_lookup_error. + (cp_parser_parenthesized_expression_list): Improve comments. + (cp_parser_condition): Adjust call to cp_parser_declarator. + (cp_parser_template_parameter): Adjust call to + cp_parser_parameter_declaration. + (cp_parser_template_argument_list): Set + in_template_argument_list_p. + (cp_parser_explicit_instantiation): Adjust call to + cp_parser_declarator. + (cp_parser_simple_type_specifier): Remove unncessary code. + (cp_parser_using_declaration): Use cp_parser_name_lookup_error. + (cp_parser_init_declarator): Handle member function definitions. + (cp_parser_direct_declarator): Adjust call to + cp_parser_declarator. + (cp_parser_type_id): Adjust call to cp_parser_declarator. + (cp_parser_parameter_declaration_list): Avoid backtracking where + possible. + (cp_parser_parameter_declaration): Add parenthesized_p parameter. + (cp_parser_function_definition): Remove. + (cp_parser_member_declaration): Do not backtrack to look for + function definitions. + (cp_parser_exception_declaration): Adjust call to + cp_parser_declarator. + (cp_parser_single_declaration): Handle function definitions via + cp_parser_init_declarator. + (cp_parser_save_member_function_body): New function. + 2003-12-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> PR c++/13106 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 69bc78e..4709ccb 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1243,6 +1243,9 @@ typedef struct cp_parser GTY(()) direct-declarator. */ bool in_declarator_p; + /* TRUE if we are presently parsing a template-argument-list. */ + bool in_template_argument_list_p; + /* TRUE if we are presently parsing the body of an iteration-statement. */ bool in_iteration_statement_p; @@ -1470,7 +1473,7 @@ static void cp_parser_linkage_specification static tree cp_parser_init_declarator (cp_parser *, tree, tree, bool, bool, int, bool *); static tree cp_parser_declarator - (cp_parser *, cp_parser_declarator_kind, int *); + (cp_parser *, cp_parser_declarator_kind, int *, bool *); static tree cp_parser_direct_declarator (cp_parser *, cp_parser_declarator_kind, int *); static enum tree_code cp_parser_ptr_operator @@ -1490,9 +1493,7 @@ static tree cp_parser_parameter_declaration_clause static tree cp_parser_parameter_declaration_list (cp_parser *); static tree cp_parser_parameter_declaration - (cp_parser *, bool); -static tree cp_parser_function_definition - (cp_parser *, bool *); + (cp_parser *, bool, bool *); static void cp_parser_function_body (cp_parser *); static tree cp_parser_initializer @@ -1644,6 +1645,8 @@ static tree cp_parser_single_declaration (cp_parser *, bool, bool *); static tree cp_parser_functional_cast (cp_parser *, tree); +static tree cp_parser_save_member_function_body + (cp_parser *, tree, tree, tree); static tree cp_parser_enclosed_template_argument_list (cp_parser *); static void cp_parser_save_default_args @@ -1696,6 +1699,8 @@ static bool cp_parser_committed_to_tentative_parse (cp_parser *); static void cp_parser_error (cp_parser *, const char *); +static void cp_parser_name_lookup_error + (cp_parser *, tree, tree, const char *); static bool cp_parser_simulate_error (cp_parser *); static void cp_parser_check_type_definition @@ -1760,7 +1765,42 @@ cp_parser_error (cp_parser* parser, const char* message) { /* Output the MESSAGE -- unless we're parsing tentatively. */ if (!cp_parser_simulate_error (parser)) - error (message); + { + cp_token *token; + token = cp_lexer_peek_token (parser->lexer); + c_parse_error (message, token->type, token->value); + } +} + +/* Issue an error about name-lookup failing. NAME is the + IDENTIFIER_NODE DECL is the result of + the lookup (as returned from cp_parser_lookup_name). DESIRED is + the thing that we hoped to find. */ + +static void +cp_parser_name_lookup_error (cp_parser* parser, + tree name, + tree decl, + const char* desired) +{ + /* If name lookup completely failed, tell the user that NAME was not + declared. */ + if (decl == error_mark_node) + { + if (parser->scope && parser->scope != global_namespace) + error ("`%D::%D' has not been declared", + parser->scope, name); + else if (parser->scope == global_namespace) + error ("`::%D' has not been declared", name); + else + error ("`%D' has not been declared", name); + } + else if (parser->scope && parser->scope != global_namespace) + error ("`%D::%D' %s", parser->scope, name, desired); + else if (parser->scope == global_namespace) + error ("`::%D' %s", name, desired); + else + error ("`%D' %s", name, desired); } /* If we are parsing tentatively, remember that an error has occurred @@ -2194,6 +2234,9 @@ cp_parser_new (void) /* We are not processing a declarator. */ parser->in_declarator_p = false; + /* We are not processing a template-argument-list. */ + parser->in_template_argument_list_p = false; + /* We are not in an iteration statement. */ parser->in_iteration_statement_p = false; @@ -3087,24 +3130,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, if (TREE_CODE (decl) == TEMPLATE_DECL) error ("`%D' used without template parameters", decl); - else if (parser->scope) - { - if (TYPE_P (parser->scope)) - error ("`%T::%D' is not a class-name or " - "namespace-name", - parser->scope, token->value); - else if (parser->scope == global_namespace) - error ("`::%D' is not a class-name or " - "namespace-name", - token->value); - else - error ("`%D::%D' is not a class-name or " - "namespace-name", - parser->scope, token->value); - } else - error ("`%D' is not a class-name or namespace-name", - token->value); + cp_parser_name_lookup_error + (parser, token->value, decl, + "is not a class or namespace"); parser->scope = NULL_TREE; error_p = true; /* Treat this as a successful nested-name-specifier @@ -3958,7 +3987,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, skip_comma:; /* We try and resync to an unnested comma, as that will give the user better diagnostics. */ - ending = cp_parser_skip_to_closing_parenthesis (parser, true, true, + ending = cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/true, /*consume_paren=*/true); if (ending < 0) goto get_comma; @@ -5621,7 +5652,8 @@ cp_parser_condition (cp_parser* parser) /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - /*ctor_dtor_or_conv_p=*/NULL); + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL); /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); /* Parse the asm-specification. */ @@ -7449,7 +7481,8 @@ cp_parser_template_parameter (cp_parser* parser) of the template parameter-list rather than a greater-than operator. */ return - cp_parser_parameter_declaration (parser, /*template_parm_p=*/true); + cp_parser_parameter_declaration (parser, /*template_parm_p=*/true, + /*parenthesized_p=*/NULL); } /* Parse a type-parameter. @@ -7927,7 +7960,10 @@ cp_parser_template_argument_list (cp_parser* parser) unsigned alloced = 10; tree *arg_ary = fixed_args; tree vec; + bool saved_in_template_argument_list_p; + saved_in_template_argument_list_p = parser->in_template_argument_list_p; + parser->in_template_argument_list_p = true; do { tree argument; @@ -7961,6 +7997,7 @@ cp_parser_template_argument_list (cp_parser* parser) if (arg_ary != fixed_args) free (arg_ary); + parser->in_template_argument_list_p = saved_in_template_argument_list_p; return vec; } @@ -8207,7 +8244,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - /*ctor_dtor_or_conv_p=*/NULL); + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL); cp_parser_check_for_definition_in_return_type (declarator, declares_class_or_enum); decl = grokdeclarator (declarator, decl_specifiers, @@ -8548,12 +8586,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags, } /* Otherwise, look for a type-name. */ else - { - type = cp_parser_type_name (parser); - if (type == error_mark_node) - type = NULL_TREE; - } - + type = cp_parser_type_name (parser); /* If it didn't work out, we don't have a TYPE. */ if ((flags & CP_PARSER_FLAGS_OPTIONAL) && !cp_parser_parse_definitely (parser)) @@ -8570,7 +8603,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags, /* There is no valid C++ program where a non-template type is followed by a "<". That usually indicates that the user thought that the type was a template. */ - if (type) + if (type && type != error_mark_node) cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type)); return type; @@ -8620,7 +8653,9 @@ cp_parser_type_name (cp_parser* parser) /* Issue an error if we did not find a type-name. */ if (TREE_CODE (type_decl) != TYPE_DECL) { - cp_parser_error (parser, "expected type-name"); + if (!cp_parser_simulate_error (parser)) + cp_parser_name_lookup_error (parser, identifier, type_decl, + "is not a type"); type_decl = error_mark_node; } /* Remember that the name was used in the definition of the @@ -9265,13 +9300,7 @@ cp_parser_using_declaration (cp_parser* parser) { decl = cp_parser_lookup_name_simple (parser, identifier); if (decl == error_mark_node) - { - if (parser->scope && parser->scope != global_namespace) - error ("`%D::%D' has not been declared", - parser->scope, identifier); - else - error ("`::%D' has not been declared", identifier); - } + cp_parser_name_lookup_error (parser, identifier, decl, NULL); else if (scope) do_local_using_decl (decl); else @@ -9469,6 +9498,16 @@ cp_parser_asm_definition (cp_parser* parser) init-declarator: declarator asm-specification [opt] attributes [opt] initializer [opt] + function-definition: + decl-specifier-seq [opt] declarator ctor-initializer [opt] + function-body + decl-specifier-seq [opt] declarator function-try-block + + GNU Extension: + + function-definition: + __extension__ function-definition + The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator. Returns a representation of the entity declared. If MEMBER_P is TRUE, then this declarator appears in a class scope. The new DECL created @@ -9518,7 +9557,8 @@ cp_parser_init_declarator (cp_parser* parser, /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - &ctor_dtor_or_conv_p); + &ctor_dtor_or_conv_p, + /*parenthesized_p=*/NULL); /* Gather up the deferred checks. */ stop_deferring_access_checks (); @@ -9576,8 +9616,15 @@ cp_parser_init_declarator (cp_parser* parser, *function_definition_p = true; /* Parse the function definition. */ - decl = (cp_parser_function_definition_from_specifiers_and_declarator - (parser, decl_specifiers, prefix_attributes, declarator)); + if (member_p) + decl = cp_parser_save_member_function_body (parser, + decl_specifiers, + declarator, + prefix_attributes); + else + decl + = (cp_parser_function_definition_from_specifiers_and_declarator + (parser, decl_specifiers, prefix_attributes, declarator)); return decl; } @@ -9780,12 +9827,16 @@ cp_parser_init_declarator (cp_parser* parser, semantic analysis, rather than parsing, but that makes it difficult to handle something like `f()'. We want to notice that there are no decl-specifiers, and therefore realize that this is an - expression, not a declaration.) */ + expression, not a declaration.) + + If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff + the declarator is a direct-declarator of the form "(...)". */ static tree cp_parser_declarator (cp_parser* parser, cp_parser_declarator_kind dcl_kind, - int* ctor_dtor_or_conv_p) + int* ctor_dtor_or_conv_p, + bool* parenthesized_p) { cp_token *token; tree declarator; @@ -9814,6 +9865,10 @@ cp_parser_declarator (cp_parser* parser, /* If that worked, then we have a ptr-operator. */ if (cp_parser_parse_definitely (parser)) { + /* If a ptr-operator was found, then this declarator was not + parenthesized. */ + if (parenthesized_p) + *parenthesized_p = true; /* The dependent declarator is optional if we are parsing an abstract-declarator. */ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED) @@ -9821,7 +9876,8 @@ cp_parser_declarator (cp_parser* parser, /* Parse the dependent declarator. */ declarator = cp_parser_declarator (parser, dcl_kind, - /*ctor_dtor_or_conv_p=*/NULL); + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL); /* If we are parsing an abstract-declarator, we must handle the case where the dependent declarator is absent. */ @@ -9842,8 +9898,13 @@ cp_parser_declarator (cp_parser* parser, } /* Everything else is a direct-declarator. */ else - declarator = cp_parser_direct_declarator (parser, dcl_kind, - ctor_dtor_or_conv_p); + { + if (parenthesized_p) + *parenthesized_p = cp_lexer_next_token_is (parser->lexer, + CPP_OPEN_PAREN); + declarator = cp_parser_direct_declarator (parser, dcl_kind, + ctor_dtor_or_conv_p); + } if (attributes && declarator != error_mark_node) declarator = tree_cons (attributes, declarator, NULL_TREE); @@ -10017,7 +10078,8 @@ cp_parser_direct_declarator (cp_parser* parser, cp_lexer_consume_token (parser->lexer); /* Parse the nested declarator. */ declarator - = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p); + = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p, + /*parenthesized_p=*/NULL); first = false; /* Expect a `)'. */ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) @@ -10428,7 +10490,8 @@ cp_parser_type_id (cp_parser* parser) cp_parser_parse_tentatively (parser); /* Look for the declarator. */ abstract_declarator - = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL); + = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL, + /*parenthesized_p=*/NULL); /* Check to see if there really was a declarator. */ if (!cp_parser_parse_definitely (parser)) abstract_declarator = NULL_TREE; @@ -10604,9 +10667,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser) while (true) { tree parameter; + bool parenthesized_p; /* Parse the parameter. */ parameter - = cp_parser_parameter_declaration (parser, /*template_parm_p=*/false); + = cp_parser_parameter_declaration (parser, + /*template_parm_p=*/false, + &parenthesized_p); /* If a parse error occurred parsing the parameter declaration, then the entire parameter-declaration-list is erroneous. */ @@ -10636,10 +10702,37 @@ cp_parser_parameter_declaration_list (cp_parser* parser) /* Otherwise, there must be more parameters. Consume the `,'. */ cp_lexer_consume_token (parser->lexer); + /* When parsing something like: + + int i(float f, double d) + + we can tell after seeing the declaration for "f" that we + are not looking at an initialization of a variable "i", + but rather at the declaration of a function "i". + + Due to the fact that the parsing of template arguments + (as specified to a template-id) requires backtracking we + cannot use this technique when inside a template argument + list. */ + if (!parser->in_template_argument_list_p + && cp_parser_parsing_tentatively (parser) + && !cp_parser_committed_to_tentative_parse (parser) + /* However, a parameter-declaration of the form + "foat(f)" (which is a valid declaration of a + parameter "f") can also be interpreted as an + expression (the conversion of "f" to "float"). */ + && !parenthesized_p) + cp_parser_commit_to_tentative_parse (parser); } else { cp_parser_error (parser, "expected `,' or `...'"); + if (!cp_parser_parsing_tentatively (parser) + || cp_parser_committed_to_tentative_parse (parser)) + cp_parser_skip_to_closing_parenthesis (parser, + /*recovering=*/true, + /*or_comma=*/true, + /*consume_paren=*/false); break; } } @@ -10662,14 +10755,18 @@ cp_parser_parameter_declaration_list (cp_parser* parser) is not interpreted as a greater-than operator.) Returns a TREE_LIST representing the parameter-declaration. The - TREE_VALUE is a representation of the decl-specifier-seq and - declarator. In particular, the TREE_VALUE will be a TREE_LIST - whose TREE_PURPOSE represents the decl-specifier-seq and whose - TREE_VALUE represents the declarator. */ + TREE_PURPOSE is the default argument expression, or NULL_TREE if + there is no default argument. The TREE_VALUE is a representation + of the decl-specifier-seq and declarator. In particular, the + TREE_VALUE will be a TREE_LIST whose TREE_PURPOSE represents the + decl-specifier-seq and whose TREE_VALUE represents the declarator. + If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff + the declarator is of the form "(p)". */ static tree cp_parser_parameter_declaration (cp_parser *parser, - bool template_parm_p) + bool template_parm_p, + bool *parenthesized_p) { int declares_class_or_enum; bool greater_than_is_operator_p; @@ -10719,7 +10816,11 @@ cp_parser_parameter_declaration (cp_parser *parser, || token->type == CPP_EQ || token->type == CPP_ELLIPSIS || token->type == CPP_GREATER) - declarator = NULL_TREE; + { + declarator = NULL_TREE; + if (parenthesized_p) + *parenthesized_p = false; + } /* Otherwise, there should be a declarator. */ else { @@ -10728,7 +10829,8 @@ cp_parser_parameter_declaration (cp_parser *parser, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, - /*ctor_dtor_or_conv_p=*/NULL); + /*ctor_dtor_or_conv_p=*/NULL, + parenthesized_p); parser->default_arg_ok_p = saved_default_arg_ok_p; /* After the declarator, allow more attributes. */ attributes = chainon (attributes, cp_parser_attributes_opt (parser)); @@ -10882,184 +10984,6 @@ cp_parser_parameter_declaration (cp_parser *parser, return parameter; } -/* Parse a function-definition. - - function-definition: - decl-specifier-seq [opt] declarator ctor-initializer [opt] - function-body - decl-specifier-seq [opt] declarator function-try-block - - GNU Extension: - - function-definition: - __extension__ function-definition - - Returns the FUNCTION_DECL for the function. If FRIEND_P is - non-NULL, *FRIEND_P is set to TRUE iff the function was declared to - be a `friend'. */ - -static tree -cp_parser_function_definition (cp_parser* parser, bool* friend_p) -{ - tree decl_specifiers; - tree attributes; - tree declarator; - tree fn; - cp_token *token; - int declares_class_or_enum; - bool member_p; - /* The saved value of the PEDANTIC flag. */ - int saved_pedantic; - - /* Any pending qualification must be cleared by our caller. It is - more robust to force the callers to clear PARSER->SCOPE than to - do it here since if the qualification is in effect here, it might - also end up in effect elsewhere that it is not intended. */ - my_friendly_assert (!parser->scope, 20010821); - - /* Handle `__extension__'. */ - if (cp_parser_extension_opt (parser, &saved_pedantic)) - { - /* Parse the function-definition. */ - fn = cp_parser_function_definition (parser, friend_p); - /* Restore the PEDANTIC flag. */ - pedantic = saved_pedantic; - - return fn; - } - - /* Check to see if this definition appears in a class-specifier. */ - member_p = (at_class_scope_p () - && TYPE_BEING_DEFINED (current_class_type)); - /* Defer access checks in the decl-specifier-seq until we know what - function is being defined. There is no need to do this for the - definition of member functions; we cannot be defining a member - from another class. */ - push_deferring_access_checks (member_p ? dk_no_check: dk_deferred); - - /* Parse the decl-specifier-seq. */ - decl_specifiers - = cp_parser_decl_specifier_seq (parser, - CP_PARSER_FLAGS_OPTIONAL, - &attributes, - &declares_class_or_enum); - /* Figure out whether this declaration is a `friend'. */ - if (friend_p) - *friend_p = cp_parser_friend_p (decl_specifiers); - - /* Parse the declarator. */ - declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - /*ctor_dtor_or_conv_p=*/NULL); - - /* Gather up any access checks that occurred. */ - stop_deferring_access_checks (); - - /* If something has already gone wrong, we may as well stop now. */ - if (declarator == error_mark_node) - { - /* Skip to the end of the function, or if this wasn't anything - like a function-definition, to a `;' in the hopes of finding - a sensible place from which to continue parsing. */ - cp_parser_skip_to_end_of_block_or_statement (parser); - pop_deferring_access_checks (); - return error_mark_node; - } - - /* The next character should be a `{' (for a simple function - definition), a `:' (for a ctor-initializer), or `try' (for a - function-try block). */ - token = cp_lexer_peek_token (parser->lexer); - if (!cp_parser_token_starts_function_definition_p (token)) - { - /* Issue the error-message. */ - cp_parser_error (parser, "expected function-definition"); - /* Skip to the next `;'. */ - cp_parser_skip_to_end_of_block_or_statement (parser); - - pop_deferring_access_checks (); - return error_mark_node; - } - - cp_parser_check_for_definition_in_return_type (declarator, - declares_class_or_enum); - - /* If we are in a class scope, then we must handle - function-definitions specially. In particular, we save away the - tokens that make up the function body, and parse them again - later, in order to handle code like: - - struct S { - int f () { return i; } - int i; - }; - - Here, we cannot parse the body of `f' until after we have seen - the declaration of `i'. */ - if (member_p) - { - cp_token_cache *cache; - - /* Create the function-declaration. */ - fn = start_method (decl_specifiers, declarator, attributes); - /* If something went badly wrong, bail out now. */ - if (fn == error_mark_node) - { - /* If there's a function-body, skip it. */ - if (cp_parser_token_starts_function_definition_p - (cp_lexer_peek_token (parser->lexer))) - cp_parser_skip_to_end_of_block_or_statement (parser); - pop_deferring_access_checks (); - return error_mark_node; - } - - /* Remember it, if there default args to post process. */ - cp_parser_save_default_args (parser, fn); - - /* Create a token cache. */ - cache = cp_token_cache_new (); - /* Save away the tokens that make up the body of the - function. */ - cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0); - /* Handle function try blocks. */ - while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH)) - cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0); - - /* Save away the inline definition; we will process it when the - class is complete. */ - DECL_PENDING_INLINE_INFO (fn) = cache; - DECL_PENDING_INLINE_P (fn) = 1; - - /* We need to know that this was defined in the class, so that - friend templates are handled correctly. */ - DECL_INITIALIZED_IN_CLASS_P (fn) = 1; - - /* We're done with the inline definition. */ - finish_method (fn); - - /* Add FN to the queue of functions to be parsed later. */ - TREE_VALUE (parser->unparsed_functions_queues) - = tree_cons (NULL_TREE, fn, - TREE_VALUE (parser->unparsed_functions_queues)); - - pop_deferring_access_checks (); - return fn; - } - - /* Check that the number of template-parameter-lists is OK. */ - if (!cp_parser_check_declarator_template_parameters (parser, - declarator)) - { - cp_parser_skip_to_end_of_block_or_statement (parser); - pop_deferring_access_checks (); - return error_mark_node; - } - - fn = cp_parser_function_definition_from_specifiers_and_declarator - (parser, decl_specifiers, attributes, declarator); - pop_deferring_access_checks (); - return fn; -} - /* Parse a function-body. function-body: @@ -12035,10 +11959,6 @@ cp_parser_member_declaration (cp_parser* parser) return; } - /* We can't tell whether we're looking at a declaration or a - function-definition. */ - cp_parser_parse_tentatively (parser); - /* Parse the decl-specifier-seq. */ decl_specifiers = cp_parser_decl_specifier_seq (parser, @@ -12205,7 +12125,8 @@ cp_parser_member_declaration (cp_parser* parser) /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, - &ctor_dtor_or_conv_p); + &ctor_dtor_or_conv_p, + /*parenthesized_p=*/NULL); /* If something went wrong parsing the declarator, make sure that we at least consume some tokens. */ @@ -12213,7 +12134,15 @@ cp_parser_member_declaration (cp_parser* parser) { /* Skip to the end of the statement. */ cp_parser_skip_to_end_of_statement (parser); - break; + /* If the next token is not a semicolon, that is + probably because we just skipped over the body of + a function. So, we consume a semicolon if + present, but do not issue an error message if it + is not present. */ + if (cp_lexer_next_token_is (parser->lexer, + CPP_SEMICOLON)) + cp_lexer_consume_token (parser->lexer); + return; } cp_parser_check_for_definition_in_return_type @@ -12254,13 +12183,8 @@ cp_parser_member_declaration (cp_parser* parser) if (TREE_CODE (declarator) == CALL_EXPR) initializer = cp_parser_pure_specifier (parser); else - { - /* This declaration cannot be a function - definition. */ - cp_parser_commit_to_tentative_parse (parser); - /* Parse the initializer. */ - initializer = cp_parser_constant_initializer (parser); - } + /* Parse the initializer. */ + initializer = cp_parser_constant_initializer (parser); } /* Otherwise, there is no initializer. */ else @@ -12273,7 +12197,28 @@ cp_parser_member_declaration (cp_parser* parser) that we are looking at a member-declarator. */ if (cp_parser_token_starts_function_definition_p (cp_lexer_peek_token (parser->lexer))) - decl = error_mark_node; + { + /* The grammar does not allow a pure-specifier to be + used when a member function is defined. (It is + possible that this fact is an oversight in the + standard, since a pure function may be defined + outside of the class-specifier. */ + if (initializer) + error ("pure-specifier on function-definition"); + decl = cp_parser_save_member_function_body (parser, + decl_specifiers, + declarator, + attributes); + /* If the member was not a friend, declare it here. */ + if (!friend_p) + finish_member_declaration (decl); + /* Peek at the next token. */ + token = cp_lexer_peek_token (parser->lexer); + /* If the next token is a semicolon, consume it. */ + if (token->type == CPP_SEMICOLON) + cp_lexer_consume_token (parser->lexer); + return; + } else { /* Create the declaration. */ @@ -12324,23 +12269,7 @@ cp_parser_member_declaration (cp_parser* parser) } } - /* If everything went well, look for the `;'. */ - if (cp_parser_parse_definitely (parser)) - { - cp_parser_require (parser, CPP_SEMICOLON, "`;'"); - return; - } - - /* Parse the function-definition. */ - decl = cp_parser_function_definition (parser, &friend_p); - /* If the member was not a friend, declare it here. */ - if (!friend_p) - finish_member_declaration (decl); - /* Peek at the next token. */ - token = cp_lexer_peek_token (parser->lexer); - /* If the next token is a semicolon, consume it. */ - if (token->type == CPP_SEMICOLON) - cp_lexer_consume_token (parser->lexer); + cp_parser_require (parser, CPP_SEMICOLON, "`;'"); } /* Parse a pure-specifier. @@ -12800,7 +12729,8 @@ cp_parser_exception_declaration (cp_parser* parser) declarator = NULL_TREE; else declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, - /*ctor_dtor_or_conv_p=*/NULL); + /*ctor_dtor_or_conv_p=*/NULL, + /*parenthesized_p=*/NULL); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; @@ -13976,10 +13906,8 @@ cp_parser_single_declaration (cp_parser* parser, tree decl = NULL_TREE; tree decl_specifiers; tree attributes; + bool function_definition_p = false; - /* Parse the dependent declaration. We don't know yet - whether it will be a function-definition. */ - cp_parser_parse_tentatively (parser); /* Defer access checks until we know what is being declared. */ push_deferring_access_checks (dk_deferred); @@ -13990,6 +13918,8 @@ cp_parser_single_declaration (cp_parser* parser, CP_PARSER_FLAGS_OPTIONAL, &attributes, &declares_class_or_enum); + if (friend_p) + *friend_p = cp_parser_friend_p (decl_specifiers); /* Gather up the access checks that occurred the decl-specifier-seq. */ stop_deferring_access_checks (); @@ -14019,10 +13949,10 @@ cp_parser_single_declaration (cp_parser* parser, decl = cp_parser_init_declarator (parser, decl_specifiers, attributes, - /*function_definition_allowed_p=*/false, + /*function_definition_allowed_p=*/true, member_p, declares_class_or_enum, - /*function_definition_p=*/NULL); + &function_definition_p); pop_deferring_access_checks (); @@ -14032,18 +13962,9 @@ cp_parser_single_declaration (cp_parser* parser, parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; /* Look for a trailing `;' after the declaration. */ - if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'") - && cp_parser_committed_to_tentative_parse (parser)) + if (!function_definition_p + && !cp_parser_require (parser, CPP_SEMICOLON, "`;'")) cp_parser_skip_to_end_of_block_or_statement (parser); - /* If it worked, set *FRIEND_P based on the DECL_SPECIFIERS. */ - if (cp_parser_parse_definitely (parser)) - { - if (friend_p) - *friend_p = cp_parser_friend_p (decl_specifiers); - } - /* Otherwise, try a function-definition. */ - else - decl = cp_parser_function_definition (parser, friend_p); return decl; } @@ -14071,6 +13992,65 @@ cp_parser_functional_cast (cp_parser* parser, tree type) return build_functional_cast (type, expression_list); } +/* Save the tokens that make up the body of a member function defined + in a class-specifier. The DECL_SPECIFIERS and DECLARATOR have + already been parsed. The ATTRIBUTES are any GNU "__attribute__" + specifiers applied to the declaration. Returns the FUNCTION_DECL + for the member function. */ + +tree +cp_parser_save_member_function_body (cp_parser* parser, + tree decl_specifiers, + tree declarator, + tree attributes) +{ + cp_token_cache *cache; + tree fn; + + /* Create the function-declaration. */ + fn = start_method (decl_specifiers, declarator, attributes); + /* If something went badly wrong, bail out now. */ + if (fn == error_mark_node) + { + /* If there's a function-body, skip it. */ + if (cp_parser_token_starts_function_definition_p + (cp_lexer_peek_token (parser->lexer))) + cp_parser_skip_to_end_of_block_or_statement (parser); + return error_mark_node; + } + + /* Remember it, if there default args to post process. */ + cp_parser_save_default_args (parser, fn); + + /* Create a token cache. */ + cache = cp_token_cache_new (); + /* Save away the tokens that make up the body of the + function. */ + cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0); + /* Handle function try blocks. */ + while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH)) + cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0); + + /* Save away the inline definition; we will process it when the + class is complete. */ + DECL_PENDING_INLINE_INFO (fn) = cache; + DECL_PENDING_INLINE_P (fn) = 1; + + /* We need to know that this was defined in the class, so that + friend templates are handled correctly. */ + DECL_INITIALIZED_IN_CLASS_P (fn) = 1; + + /* We're done with the inline definition. */ + finish_method (fn); + + /* Add FN to the queue of functions to be parsed later. */ + TREE_VALUE (parser->unparsed_functions_queues) + = tree_cons (NULL_TREE, fn, + TREE_VALUE (parser->unparsed_functions_queues)); + + return fn; +} + /* Parse a template-argument-list, as well as the trailing ">" (but not the opening ">"). See cp_parser_template_argument_list for the return value. */ @@ -14115,7 +14095,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) return arguments; } - /* MEMBER_FUNCTION is a member function, or a friend. If default arguments, or the body of the function have not yet been parsed, parse them now. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cb89b4f..ee586f5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2003-12-14 Mark Mitchell <mark@codesourcery.com> + + PR c++/10779 + PR c++/12160 + * g++.dg/parse/error3.C: New test. + * g++.dg/parse/error4.C: Likewise. + * g++.dg/abi/mangle4.C: Tweak error messages. + * g++.dg/lookup/using5.C: Likewise. + * g++.dg/other/error2.C: Likewise. + * g++.dg/parse/typename5.C: Likewise. + * g++.dg/parse/undefined1.C: Likewise. + * g++.dg/template/arg2.C: Likewise. + * g++.dg/template/ttp3.C: Likewise. + * g++.dg/template/type1.C: Likewise. + * g++.old-deja/g++.other/crash32.C: Likewise. + * g++.old-djea/g++.pt/defarg8.C: Likewise. + 2003-12-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> PR c++/13106 diff --git a/gcc/testsuite/g++.dg/abi/mangle4.C b/gcc/testsuite/g++.dg/abi/mangle4.C index d4b5936..3ce2247 100644 --- a/gcc/testsuite/g++.dg/abi/mangle4.C +++ b/gcc/testsuite/g++.dg/abi/mangle4.C @@ -18,7 +18,7 @@ int main() C<static_cast<const A*>(&b)> c; // { dg-error "" } D<&b> d; E<const_cast<B*>(&b)> e; // { dg-error "" } - f(d, c); // { dg-error "" } - g(d, e); // { dg-error "" } + f(d, c); + g(d, e); } diff --git a/gcc/testsuite/g++.dg/lookup/using5.C b/gcc/testsuite/g++.dg/lookup/using5.C index 8aab55b..b443b97 100644 --- a/gcc/testsuite/g++.dg/lookup/using5.C +++ b/gcc/testsuite/g++.dg/lookup/using5.C @@ -13,5 +13,5 @@ template <typename> struct A template <typename T> struct B : A<T> { - using X::foo; // { dg-error "not a class-name|nested-name-specifier|non-member" } + using X::foo; // { dg-error "declared|nested-name-specifier|non-member" } }; diff --git a/gcc/testsuite/g++.dg/other/error2.C b/gcc/testsuite/g++.dg/other/error2.C index 391115d..ea6c520 100644 --- a/gcc/testsuite/g++.dg/other/error2.C +++ b/gcc/testsuite/g++.dg/other/error2.C @@ -10,5 +10,5 @@ namespace N class B { friend void operator>>(int, class B); }; class N { friend void operator>>(int,class N); }; } -void N::operator>>(int, N::B) // { dg-error "`B' is not a member of|non-function|primary-expression" "" } +void N::operator>>(int, N::B) // { dg-error "N::N::B" } { } // { dg-error "" "" } diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C new file mode 100644 index 0000000..57b7896 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/error3.C @@ -0,0 +1,6 @@ +// PR c++/10779 + +static void InstantiateConstraint(const float&, unsigned, + void(*AddFunction)(const TYPE&,bool&, // { dg-error "" } + char*, char*, + unsigned*)); diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C new file mode 100644 index 0000000..511209d --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/error4.C @@ -0,0 +1,7 @@ +// PR c++/12160 + +struct X { + virtual void f(int, + itn, // { dg-error "declared" } + int); // { dg-error "" } +}; diff --git a/gcc/testsuite/g++.dg/parse/typename5.C b/gcc/testsuite/g++.dg/parse/typename5.C index 70a2814..6b2ed89 100644 --- a/gcc/testsuite/g++.dg/parse/typename5.C +++ b/gcc/testsuite/g++.dg/parse/typename5.C @@ -8,5 +8,5 @@ template <typename> struct A {}; template <typename> struct B { - typedef A<typename X::Y> C; // { dg-error "not a class-name|invalid|no type" } + typedef A<typename X::Y> C; // { dg-error "declared|invalid|no type" } }; diff --git a/gcc/testsuite/g++.dg/parse/undefined1.C b/gcc/testsuite/g++.dg/parse/undefined1.C index 324c575..0ae4e88 100644 --- a/gcc/testsuite/g++.dg/parse/undefined1.C +++ b/gcc/testsuite/g++.dg/parse/undefined1.C @@ -7,4 +7,4 @@ struct foo foo(X) {} // { dg-error "" } foo(X y, int) : x() {} // { dg-error "" } -}; // { dg-error "" } +}; diff --git a/gcc/testsuite/g++.dg/template/arg2.C b/gcc/testsuite/g++.dg/template/arg2.C index 5a4ff27..dbed54d 100644 --- a/gcc/testsuite/g++.dg/template/arg2.C +++ b/gcc/testsuite/g++.dg/template/arg2.C @@ -10,5 +10,5 @@ template <typename T> class X {}; void fn () { class L {}; - X<L> f; // { dg-error "uses local type|trying to instantiate|expected" "" } + X<L> f; // { dg-error "uses local type|trying to instantiate|no type" "" } } diff --git a/gcc/testsuite/g++.dg/template/ttp3.C b/gcc/testsuite/g++.dg/template/ttp3.C index cc3128c..a7f231a 100644 --- a/gcc/testsuite/g++.dg/template/ttp3.C +++ b/gcc/testsuite/g++.dg/template/ttp3.C @@ -23,4 +23,4 @@ class List { }; // This next line should just do a lookup of 'class List', and then // get a type/value mismatch. Instead we try and push 'class List' // into the global namespace and get a redeclaration error. -vector<class List > data; // { dg-error "invalid|required|expected" "" } +vector<class List > data; // { dg-error "invalid|required|declaration" "" } diff --git a/gcc/testsuite/g++.dg/template/type1.C b/gcc/testsuite/g++.dg/template/type1.C index 98a4bd3..b74d975a 100644 --- a/gcc/testsuite/g++.dg/template/type1.C +++ b/gcc/testsuite/g++.dg/template/type1.C @@ -5,4 +5,4 @@ struct A { }; int A::B::c; // { dg-error "parameters" } -int A::C::d; // { dg-error "class" } +int A::C::d; // { dg-error "declared" } diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash32.C b/gcc/testsuite/g++.old-deja/g++.other/crash32.C index ad21396..b9c4cf9 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/crash32.C +++ b/gcc/testsuite/g++.old-deja/g++.other/crash32.C @@ -6,7 +6,7 @@ struct foo enum e { not // { dg-error "" } - }; // { dg-bogus "" "" { xfail *-*-* } } + }; // { dg-bogus "" } ~foo(); // { dg-bogus "" "" { xfail *-*-* } } void x (foo *&a, bool b = (unsigned char)0); }; // { dg-bogus "" "" { xfail *-*-* } } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/defarg8.C b/gcc/testsuite/g++.old-deja/g++.pt/defarg8.C index f60fffa..239672d 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/defarg8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/defarg8.C @@ -7,11 +7,11 @@ // so) template <class T> class foo1; -template <class T, class U> class foo2; +template <class T, class U> class foo2; // { dg-error "" } struct bar { template <class T, class U> - bar(int i = foo1<T>::baz, // { dg-bogus "" "" { xfail *-*-* } } - + bar(int i = foo1<T>::baz, // { dg-bogus "" } - int j = int(foo2<T, U>::baz), // ok - int k = foo2<T, U>::baz) {} // this is the problematic one. + int k = foo2<T, U>::baz) {} // { dg-error "" } }; |