Commit 4bb8ca28 by Mark Mitchell Committed by Mark Mitchell

re PR c++/10779 (Error cascade for unknown type in function prototype)

	* c-common.h (c_parse_error): Declare it.
	* c-common.c (c_parse_error): New function.
	* c-parse.y (yyerror): Use it.

	* 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.

	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.

From-SVN: r74624
parent 69f36495
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> 2003-12-14 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
PR target/13054 PR target/13054
......
...@@ -5893,4 +5893,36 @@ c_decl_uninit (tree t) ...@@ -5893,4 +5893,36 @@ c_decl_uninit (tree t)
return false; 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" #include "gt-c-common.h"
...@@ -1330,6 +1330,7 @@ extern void c_stddef_cpp_builtins (void); ...@@ -1330,6 +1330,7 @@ extern void c_stddef_cpp_builtins (void);
extern void fe_file_change (const struct line_map *); extern void fe_file_change (const struct line_map *);
extern int c_estimate_num_insns (tree decl); extern int c_estimate_num_insns (tree decl);
extern bool c_decl_uninit (tree t); 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 /* 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 in the ObjC++ world, too. What is more, stub-objc.c could use a few
......
...@@ -3551,28 +3551,7 @@ init_reswords (void) ...@@ -3551,28 +3551,7 @@ init_reswords (void)
static void static void
yyerror (const char *msgid) yyerror (const char *msgid)
{ {
const char *string = _(msgid); c_parse_error (msgid, last_token, yylval.ttype);
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));
} }
static int static int
......
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> 2003-12-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/13106 PR c++/13106
......
...@@ -1243,6 +1243,9 @@ typedef struct cp_parser GTY(()) ...@@ -1243,6 +1243,9 @@ typedef struct cp_parser GTY(())
direct-declarator. */ direct-declarator. */
bool in_declarator_p; 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 /* TRUE if we are presently parsing the body of an
iteration-statement. */ iteration-statement. */
bool in_iteration_statement_p; bool in_iteration_statement_p;
...@@ -1470,7 +1473,7 @@ static void cp_parser_linkage_specification ...@@ -1470,7 +1473,7 @@ static void cp_parser_linkage_specification
static tree cp_parser_init_declarator static tree cp_parser_init_declarator
(cp_parser *, tree, tree, bool, bool, int, bool *); (cp_parser *, tree, tree, bool, bool, int, bool *);
static tree cp_parser_declarator 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 static tree cp_parser_direct_declarator
(cp_parser *, cp_parser_declarator_kind, int *); (cp_parser *, cp_parser_declarator_kind, int *);
static enum tree_code cp_parser_ptr_operator static enum tree_code cp_parser_ptr_operator
...@@ -1490,9 +1493,7 @@ static tree cp_parser_parameter_declaration_clause ...@@ -1490,9 +1493,7 @@ static tree cp_parser_parameter_declaration_clause
static tree cp_parser_parameter_declaration_list static tree cp_parser_parameter_declaration_list
(cp_parser *); (cp_parser *);
static tree cp_parser_parameter_declaration static tree cp_parser_parameter_declaration
(cp_parser *, bool); (cp_parser *, bool, bool *);
static tree cp_parser_function_definition
(cp_parser *, bool *);
static void cp_parser_function_body static void cp_parser_function_body
(cp_parser *); (cp_parser *);
static tree cp_parser_initializer static tree cp_parser_initializer
...@@ -1644,6 +1645,8 @@ static tree cp_parser_single_declaration ...@@ -1644,6 +1645,8 @@ static tree cp_parser_single_declaration
(cp_parser *, bool, bool *); (cp_parser *, bool, bool *);
static tree cp_parser_functional_cast static tree cp_parser_functional_cast
(cp_parser *, tree); (cp_parser *, tree);
static tree cp_parser_save_member_function_body
(cp_parser *, tree, tree, tree);
static tree cp_parser_enclosed_template_argument_list static tree cp_parser_enclosed_template_argument_list
(cp_parser *); (cp_parser *);
static void cp_parser_save_default_args static void cp_parser_save_default_args
...@@ -1696,6 +1699,8 @@ static bool cp_parser_committed_to_tentative_parse ...@@ -1696,6 +1699,8 @@ static bool cp_parser_committed_to_tentative_parse
(cp_parser *); (cp_parser *);
static void cp_parser_error static void cp_parser_error
(cp_parser *, const char *); (cp_parser *, const char *);
static void cp_parser_name_lookup_error
(cp_parser *, tree, tree, const char *);
static bool cp_parser_simulate_error static bool cp_parser_simulate_error
(cp_parser *); (cp_parser *);
static void cp_parser_check_type_definition static void cp_parser_check_type_definition
...@@ -1760,7 +1765,42 @@ cp_parser_error (cp_parser* parser, const char* message) ...@@ -1760,7 +1765,42 @@ cp_parser_error (cp_parser* parser, const char* message)
{ {
/* Output the MESSAGE -- unless we're parsing tentatively. */ /* Output the MESSAGE -- unless we're parsing tentatively. */
if (!cp_parser_simulate_error (parser)) 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 /* If we are parsing tentatively, remember that an error has occurred
...@@ -2194,6 +2234,9 @@ cp_parser_new (void) ...@@ -2194,6 +2234,9 @@ cp_parser_new (void)
/* We are not processing a declarator. */ /* We are not processing a declarator. */
parser->in_declarator_p = false; 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. */ /* We are not in an iteration statement. */
parser->in_iteration_statement_p = false; parser->in_iteration_statement_p = false;
...@@ -3087,24 +3130,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, ...@@ -3087,24 +3130,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
if (TREE_CODE (decl) == TEMPLATE_DECL) if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("`%D' used without template parameters", error ("`%D' used without template parameters",
decl); 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 else
error ("`%D' is not a class-name or namespace-name", cp_parser_name_lookup_error
token->value); (parser, token->value, decl,
"is not a class or namespace");
parser->scope = NULL_TREE; parser->scope = NULL_TREE;
error_p = true; error_p = true;
/* Treat this as a successful nested-name-specifier /* Treat this as a successful nested-name-specifier
...@@ -3958,7 +3987,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, ...@@ -3958,7 +3987,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
skip_comma:; skip_comma:;
/* We try and resync to an unnested comma, as that will give the /* We try and resync to an unnested comma, as that will give the
user better diagnostics. */ 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); /*consume_paren=*/true);
if (ending < 0) if (ending < 0)
goto get_comma; goto get_comma;
...@@ -5621,7 +5652,8 @@ cp_parser_condition (cp_parser* parser) ...@@ -5621,7 +5652,8 @@ cp_parser_condition (cp_parser* parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, 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. */ /* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
/* Parse the asm-specification. */ /* Parse the asm-specification. */
...@@ -7449,7 +7481,8 @@ cp_parser_template_parameter (cp_parser* parser) ...@@ -7449,7 +7481,8 @@ cp_parser_template_parameter (cp_parser* parser)
of the template parameter-list rather than a greater-than of the template parameter-list rather than a greater-than
operator. */ operator. */
return 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. /* Parse a type-parameter.
...@@ -7927,7 +7960,10 @@ cp_parser_template_argument_list (cp_parser* parser) ...@@ -7927,7 +7960,10 @@ cp_parser_template_argument_list (cp_parser* parser)
unsigned alloced = 10; unsigned alloced = 10;
tree *arg_ary = fixed_args; tree *arg_ary = fixed_args;
tree vec; 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 do
{ {
tree argument; tree argument;
...@@ -7961,6 +7997,7 @@ cp_parser_template_argument_list (cp_parser* parser) ...@@ -7961,6 +7997,7 @@ cp_parser_template_argument_list (cp_parser* parser)
if (arg_ary != fixed_args) if (arg_ary != fixed_args)
free (arg_ary); free (arg_ary);
parser->in_template_argument_list_p = saved_in_template_argument_list_p;
return vec; return vec;
} }
...@@ -8207,7 +8244,8 @@ cp_parser_explicit_instantiation (cp_parser* parser) ...@@ -8207,7 +8244,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = 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, cp_parser_check_for_definition_in_return_type (declarator,
declares_class_or_enum); declares_class_or_enum);
decl = grokdeclarator (declarator, decl_specifiers, decl = grokdeclarator (declarator, decl_specifiers,
...@@ -8548,12 +8586,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags, ...@@ -8548,12 +8586,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
} }
/* Otherwise, look for a type-name. */ /* Otherwise, look for a type-name. */
else else
{
type = cp_parser_type_name (parser); type = cp_parser_type_name (parser);
if (type == error_mark_node)
type = NULL_TREE;
}
/* If it didn't work out, we don't have a TYPE. */ /* If it didn't work out, we don't have a TYPE. */
if ((flags & CP_PARSER_FLAGS_OPTIONAL) if ((flags & CP_PARSER_FLAGS_OPTIONAL)
&& !cp_parser_parse_definitely (parser)) && !cp_parser_parse_definitely (parser))
...@@ -8570,7 +8603,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags, ...@@ -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 /* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought followed by a "<". That usually indicates that the user thought
that the type was a template. */ 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)); cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
return type; return type;
...@@ -8620,7 +8653,9 @@ cp_parser_type_name (cp_parser* parser) ...@@ -8620,7 +8653,9 @@ cp_parser_type_name (cp_parser* parser)
/* Issue an error if we did not find a type-name. */ /* Issue an error if we did not find a type-name. */
if (TREE_CODE (type_decl) != TYPE_DECL) 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; type_decl = error_mark_node;
} }
/* Remember that the name was used in the definition of the /* Remember that the name was used in the definition of the
...@@ -9265,13 +9300,7 @@ cp_parser_using_declaration (cp_parser* parser) ...@@ -9265,13 +9300,7 @@ cp_parser_using_declaration (cp_parser* parser)
{ {
decl = cp_parser_lookup_name_simple (parser, identifier); decl = cp_parser_lookup_name_simple (parser, identifier);
if (decl == error_mark_node) if (decl == error_mark_node)
{ cp_parser_name_lookup_error (parser, identifier, decl, NULL);
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);
}
else if (scope) else if (scope)
do_local_using_decl (decl); do_local_using_decl (decl);
else else
...@@ -9469,6 +9498,16 @@ cp_parser_asm_definition (cp_parser* parser) ...@@ -9469,6 +9498,16 @@ cp_parser_asm_definition (cp_parser* parser)
init-declarator: init-declarator:
declarator asm-specification [opt] attributes [opt] initializer [opt] 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. The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
Returns a representation of the entity declared. If MEMBER_P is TRUE, Returns a representation of the entity declared. If MEMBER_P is TRUE,
then this declarator appears in a class scope. The new DECL created then this declarator appears in a class scope. The new DECL created
...@@ -9518,7 +9557,8 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -9518,7 +9557,8 @@ cp_parser_init_declarator (cp_parser* parser,
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = 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. */ /* Gather up the deferred checks. */
stop_deferring_access_checks (); stop_deferring_access_checks ();
...@@ -9576,7 +9616,14 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -9576,7 +9616,14 @@ cp_parser_init_declarator (cp_parser* parser,
*function_definition_p = true; *function_definition_p = true;
/* Parse the function definition. */ /* Parse the function definition. */
decl = (cp_parser_function_definition_from_specifiers_and_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)); (parser, decl_specifiers, prefix_attributes, declarator));
return decl; return decl;
...@@ -9780,12 +9827,16 @@ cp_parser_init_declarator (cp_parser* parser, ...@@ -9780,12 +9827,16 @@ cp_parser_init_declarator (cp_parser* parser,
semantic analysis, rather than parsing, but that makes it difficult semantic analysis, rather than parsing, but that makes it difficult
to handle something like `f()'. We want to notice that there are to handle something like `f()'. We want to notice that there are
no decl-specifiers, and therefore realize that this is an 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 static tree
cp_parser_declarator (cp_parser* parser, cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind, cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p) int* ctor_dtor_or_conv_p,
bool* parenthesized_p)
{ {
cp_token *token; cp_token *token;
tree declarator; tree declarator;
...@@ -9814,6 +9865,10 @@ cp_parser_declarator (cp_parser* parser, ...@@ -9814,6 +9865,10 @@ cp_parser_declarator (cp_parser* parser,
/* If that worked, then we have a ptr-operator. */ /* If that worked, then we have a ptr-operator. */
if (cp_parser_parse_definitely (parser)) 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 /* The dependent declarator is optional if we are parsing an
abstract-declarator. */ abstract-declarator. */
if (dcl_kind != CP_PARSER_DECLARATOR_NAMED) if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
...@@ -9821,7 +9876,8 @@ cp_parser_declarator (cp_parser* parser, ...@@ -9821,7 +9876,8 @@ cp_parser_declarator (cp_parser* parser,
/* Parse the dependent declarator. */ /* Parse the dependent declarator. */
declarator = cp_parser_declarator (parser, dcl_kind, 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 /* If we are parsing an abstract-declarator, we must handle the
case where the dependent declarator is absent. */ case where the dependent declarator is absent. */
...@@ -9842,8 +9898,13 @@ cp_parser_declarator (cp_parser* parser, ...@@ -9842,8 +9898,13 @@ cp_parser_declarator (cp_parser* parser,
} }
/* Everything else is a direct-declarator. */ /* Everything else is a direct-declarator. */
else else
{
if (parenthesized_p)
*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN);
declarator = cp_parser_direct_declarator (parser, dcl_kind, declarator = cp_parser_direct_declarator (parser, dcl_kind,
ctor_dtor_or_conv_p); ctor_dtor_or_conv_p);
}
if (attributes && declarator != error_mark_node) if (attributes && declarator != error_mark_node)
declarator = tree_cons (attributes, declarator, NULL_TREE); declarator = tree_cons (attributes, declarator, NULL_TREE);
...@@ -10017,7 +10078,8 @@ cp_parser_direct_declarator (cp_parser* parser, ...@@ -10017,7 +10078,8 @@ cp_parser_direct_declarator (cp_parser* parser,
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the nested declarator. */ /* Parse the nested declarator. */
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; first = false;
/* Expect a `)'. */ /* Expect a `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'")) if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
...@@ -10428,7 +10490,8 @@ cp_parser_type_id (cp_parser* parser) ...@@ -10428,7 +10490,8 @@ cp_parser_type_id (cp_parser* parser)
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
/* Look for the declarator. */ /* Look for the declarator. */
abstract_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. */ /* Check to see if there really was a declarator. */
if (!cp_parser_parse_definitely (parser)) if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL_TREE; abstract_declarator = NULL_TREE;
...@@ -10604,9 +10667,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser) ...@@ -10604,9 +10667,12 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
while (true) while (true)
{ {
tree parameter; tree parameter;
bool parenthesized_p;
/* Parse the parameter. */ /* Parse the parameter. */
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, /* If a parse error occurred parsing the parameter declaration,
then the entire parameter-declaration-list is erroneous. */ then the entire parameter-declaration-list is erroneous. */
...@@ -10636,10 +10702,37 @@ cp_parser_parameter_declaration_list (cp_parser* parser) ...@@ -10636,10 +10702,37 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
/* Otherwise, there must be more parameters. Consume the /* Otherwise, there must be more parameters. Consume the
`,'. */ `,'. */
cp_lexer_consume_token (parser->lexer); 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 else
{ {
cp_parser_error (parser, "expected `,' or `...'"); 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; break;
} }
} }
...@@ -10662,14 +10755,18 @@ cp_parser_parameter_declaration_list (cp_parser* parser) ...@@ -10662,14 +10755,18 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
is not interpreted as a greater-than operator.) is not interpreted as a greater-than operator.)
Returns a TREE_LIST representing the parameter-declaration. The Returns a TREE_LIST representing the parameter-declaration. The
TREE_VALUE is a representation of the decl-specifier-seq and TREE_PURPOSE is the default argument expression, or NULL_TREE if
declarator. In particular, the TREE_VALUE will be a TREE_LIST there is no default argument. The TREE_VALUE is a representation
whose TREE_PURPOSE represents the decl-specifier-seq and whose of the decl-specifier-seq and declarator. In particular, the
TREE_VALUE represents the declarator. */ 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 static tree
cp_parser_parameter_declaration (cp_parser *parser, cp_parser_parameter_declaration (cp_parser *parser,
bool template_parm_p) bool template_parm_p,
bool *parenthesized_p)
{ {
int declares_class_or_enum; int declares_class_or_enum;
bool greater_than_is_operator_p; bool greater_than_is_operator_p;
...@@ -10719,7 +10816,11 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -10719,7 +10816,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
|| token->type == CPP_EQ || token->type == CPP_EQ
|| token->type == CPP_ELLIPSIS || token->type == CPP_ELLIPSIS
|| token->type == CPP_GREATER) || token->type == CPP_GREATER)
{
declarator = NULL_TREE; declarator = NULL_TREE;
if (parenthesized_p)
*parenthesized_p = false;
}
/* Otherwise, there should be a declarator. */ /* Otherwise, there should be a declarator. */
else else
{ {
...@@ -10728,7 +10829,8 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -10728,7 +10829,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
declarator = cp_parser_declarator (parser, declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_EITHER, 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; parser->default_arg_ok_p = saved_default_arg_ok_p;
/* After the declarator, allow more attributes. */ /* After the declarator, allow more attributes. */
attributes = chainon (attributes, cp_parser_attributes_opt (parser)); attributes = chainon (attributes, cp_parser_attributes_opt (parser));
...@@ -10882,184 +10984,6 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -10882,184 +10984,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
return parameter; 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. /* Parse a function-body.
function-body: function-body:
...@@ -12035,10 +11959,6 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12035,10 +11959,6 @@ cp_parser_member_declaration (cp_parser* parser)
return; 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. */ /* Parse the decl-specifier-seq. */
decl_specifiers decl_specifiers
= cp_parser_decl_specifier_seq (parser, = cp_parser_decl_specifier_seq (parser,
...@@ -12205,7 +12125,8 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12205,7 +12125,8 @@ cp_parser_member_declaration (cp_parser* parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, = 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 /* If something went wrong parsing the declarator, make sure
that we at least consume some tokens. */ that we at least consume some tokens. */
...@@ -12213,7 +12134,15 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12213,7 +12134,15 @@ cp_parser_member_declaration (cp_parser* parser)
{ {
/* Skip to the end of the statement. */ /* Skip to the end of the statement. */
cp_parser_skip_to_end_of_statement (parser); 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 cp_parser_check_for_definition_in_return_type
...@@ -12254,14 +12183,9 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12254,14 +12183,9 @@ cp_parser_member_declaration (cp_parser* parser)
if (TREE_CODE (declarator) == CALL_EXPR) if (TREE_CODE (declarator) == CALL_EXPR)
initializer = cp_parser_pure_specifier (parser); initializer = cp_parser_pure_specifier (parser);
else else
{
/* This declaration cannot be a function
definition. */
cp_parser_commit_to_tentative_parse (parser);
/* Parse the initializer. */ /* Parse the initializer. */
initializer = cp_parser_constant_initializer (parser); initializer = cp_parser_constant_initializer (parser);
} }
}
/* Otherwise, there is no initializer. */ /* Otherwise, there is no initializer. */
else else
initializer = NULL_TREE; initializer = NULL_TREE;
...@@ -12273,7 +12197,28 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -12273,7 +12197,28 @@ cp_parser_member_declaration (cp_parser* parser)
that we are looking at a member-declarator. */ that we are looking at a member-declarator. */
if (cp_parser_token_starts_function_definition_p if (cp_parser_token_starts_function_definition_p
(cp_lexer_peek_token (parser->lexer))) (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 else
{ {
/* Create the declaration. */ /* Create the declaration. */
...@@ -12324,23 +12269,7 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -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, "`;'"); 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);
} }
/* Parse a pure-specifier. /* Parse a pure-specifier.
...@@ -12800,7 +12729,8 @@ cp_parser_exception_declaration (cp_parser* parser) ...@@ -12800,7 +12729,8 @@ cp_parser_exception_declaration (cp_parser* parser)
declarator = NULL_TREE; declarator = NULL_TREE;
else else
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER, 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. */ /* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
...@@ -13976,10 +13906,8 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -13976,10 +13906,8 @@ cp_parser_single_declaration (cp_parser* parser,
tree decl = NULL_TREE; tree decl = NULL_TREE;
tree decl_specifiers; tree decl_specifiers;
tree attributes; 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. */ /* Defer access checks until we know what is being declared. */
push_deferring_access_checks (dk_deferred); push_deferring_access_checks (dk_deferred);
...@@ -13990,6 +13918,8 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -13990,6 +13918,8 @@ cp_parser_single_declaration (cp_parser* parser,
CP_PARSER_FLAGS_OPTIONAL, CP_PARSER_FLAGS_OPTIONAL,
&attributes, &attributes,
&declares_class_or_enum); &declares_class_or_enum);
if (friend_p)
*friend_p = cp_parser_friend_p (decl_specifiers);
/* Gather up the access checks that occurred the /* Gather up the access checks that occurred the
decl-specifier-seq. */ decl-specifier-seq. */
stop_deferring_access_checks (); stop_deferring_access_checks ();
...@@ -14019,10 +13949,10 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -14019,10 +13949,10 @@ cp_parser_single_declaration (cp_parser* parser,
decl = cp_parser_init_declarator (parser, decl = cp_parser_init_declarator (parser,
decl_specifiers, decl_specifiers,
attributes, attributes,
/*function_definition_allowed_p=*/false, /*function_definition_allowed_p=*/true,
member_p, member_p,
declares_class_or_enum, declares_class_or_enum,
/*function_definition_p=*/NULL); &function_definition_p);
pop_deferring_access_checks (); pop_deferring_access_checks ();
...@@ -14032,18 +13962,9 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -14032,18 +13962,9 @@ cp_parser_single_declaration (cp_parser* parser,
parser->qualifying_scope = NULL_TREE; parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE; parser->object_scope = NULL_TREE;
/* Look for a trailing `;' after the declaration. */ /* Look for a trailing `;' after the declaration. */
if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'") if (!function_definition_p
&& cp_parser_committed_to_tentative_parse (parser)) && !cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
cp_parser_skip_to_end_of_block_or_statement (parser); 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; return decl;
} }
...@@ -14071,6 +13992,65 @@ cp_parser_functional_cast (cp_parser* parser, tree type) ...@@ -14071,6 +13992,65 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
return build_functional_cast (type, expression_list); 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 /* Parse a template-argument-list, as well as the trailing ">" (but
not the opening ">"). See cp_parser_template_argument_list for the not the opening ">"). See cp_parser_template_argument_list for the
return value. */ return value. */
...@@ -14115,7 +14095,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser) ...@@ -14115,7 +14095,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
return arguments; return arguments;
} }
/* MEMBER_FUNCTION is a member function, or a friend. If default /* MEMBER_FUNCTION is a member function, or a friend. If default
arguments, or the body of the function have not yet been parsed, arguments, or the body of the function have not yet been parsed,
parse them now. */ parse them now. */
......
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> 2003-12-14 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/13106 PR c++/13106
......
...@@ -18,7 +18,7 @@ int main() ...@@ -18,7 +18,7 @@ int main()
C<static_cast<const A*>(&b)> c; // { dg-error "" } C<static_cast<const A*>(&b)> c; // { dg-error "" }
D<&b> d; D<&b> d;
E<const_cast<B*>(&b)> e; // { dg-error "" } E<const_cast<B*>(&b)> e; // { dg-error "" }
f(d, c); // { dg-error "" } f(d, c);
g(d, e); // { dg-error "" } g(d, e);
} }
...@@ -13,5 +13,5 @@ template <typename> struct A ...@@ -13,5 +13,5 @@ template <typename> struct A
template <typename T> struct B : A<T> 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" }
}; };
...@@ -10,5 +10,5 @@ namespace N ...@@ -10,5 +10,5 @@ namespace N
class B { friend void operator>>(int, class B); }; class B { friend void operator>>(int, class B); };
class N { friend void operator>>(int,class N); }; 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 "" "" } { } // { dg-error "" "" }
// PR c++/10779
static void InstantiateConstraint(const float&, unsigned,
void(*AddFunction)(const TYPE&,bool&, // { dg-error "" }
char*, char*,
unsigned*));
// PR c++/12160
struct X {
virtual void f(int,
itn, // { dg-error "declared" }
int); // { dg-error "" }
};
...@@ -8,5 +8,5 @@ template <typename> struct A {}; ...@@ -8,5 +8,5 @@ template <typename> struct A {};
template <typename> struct B 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" }
}; };
...@@ -7,4 +7,4 @@ struct foo ...@@ -7,4 +7,4 @@ struct foo
foo(X) {} // { dg-error "" } foo(X) {} // { dg-error "" }
foo(X y, int) : x() {} // { dg-error "" } foo(X y, int) : x() {} // { dg-error "" }
}; // { dg-error "" } };
...@@ -10,5 +10,5 @@ template <typename T> class X {}; ...@@ -10,5 +10,5 @@ template <typename T> class X {};
void fn () void fn ()
{ {
class L {}; 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" "" }
} }
...@@ -23,4 +23,4 @@ class List { }; ...@@ -23,4 +23,4 @@ class List { };
// This next line should just do a lookup of 'class List', and then // 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' // get a type/value mismatch. Instead we try and push 'class List'
// into the global namespace and get a redeclaration error. // 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" "" }
...@@ -5,4 +5,4 @@ struct A { ...@@ -5,4 +5,4 @@ struct A {
}; };
int A::B::c; // { dg-error "parameters" } int A::B::c; // { dg-error "parameters" }
int A::C::d; // { dg-error "class" } int A::C::d; // { dg-error "declared" }
...@@ -6,7 +6,7 @@ struct foo ...@@ -6,7 +6,7 @@ struct foo
enum e enum e
{ {
not // { dg-error "" } not // { dg-error "" }
}; // { dg-bogus "" "" { xfail *-*-* } } }; // { dg-bogus "" }
~foo(); // { dg-bogus "" "" { xfail *-*-* } } ~foo(); // { dg-bogus "" "" { xfail *-*-* } }
void x (foo *&a, bool b = (unsigned char)0); void x (foo *&a, bool b = (unsigned char)0);
}; // { dg-bogus "" "" { xfail *-*-* } } }; // { dg-bogus "" "" { xfail *-*-* } }
......
...@@ -7,11 +7,11 @@ ...@@ -7,11 +7,11 @@
// so) // so)
template <class T> class foo1; template <class T> class foo1;
template <class T, class U> class foo2; template <class T, class U> class foo2; // { dg-error "" }
struct bar { struct bar {
template <class T, class U> 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 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 "" }
}; };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment