Commit 62b8a44e by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/9109 (parse ambiguity)

cp:
	PR c++/9109
	* parser.c (cp_parser_declarator_kind): New enum.
	(cp_parser_declarator): Adjust.
	(cp_parser_direct_declarator): Adjust. Allow for either named or
	abstract declarator. Prefer abstract, if possible. Allow
	parenthesized function name.
	(cp_parser_condition): Adjust cp_parser_declarator call.
	(cp_parser_explicit_instantiation): Likewise.
	(cp_parser_init_declarator): Likewise.
	(cp_parser_type_id): Likewise.
	(cp_parser_function_definition): Likewise.
	(cp_parser_member_declaration): Likewise.
	(cp_parser_parameter_declaration): Use cp_parser_declarator to do
	the tentative parsing.
	(cp_parser_exception_declaration): Likewise.
testsuite:
	* g++.dg/parse/ambig1.C: New test.
	* g++.dg/parse/defarg2.C: New test.

From-SVN: r60944
parent e914a571
2003-01-06 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9109
* parser.c (cp_parser_declarator_kind): New enum.
(cp_parser_declarator): Adjust.
(cp_parser_direct_declarator): Adjust. Allow for either named or
abstract declarator. Prefer abstract, if possible. Allow
parenthesized function name.
(cp_parser_condition): Adjust cp_parser_declarator call.
(cp_parser_explicit_instantiation): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_type_id): Likewise.
(cp_parser_function_definition): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_parameter_declaration): Use cp_parser_declarator to do
the tentative parsing.
(cp_parser_exception_declaration): Likewise.
2003-01-05 Mark Mitchell <mark@codesourcery.com> 2003-01-05 Mark Mitchell <mark@codesourcery.com>
* parser.c (cp_parser_template_parameter): Adjust call to * parser.c (cp_parser_template_parameter): Adjust call to
......
...@@ -1124,6 +1124,18 @@ typedef enum cp_parser_id_kind ...@@ -1124,6 +1124,18 @@ typedef enum cp_parser_id_kind
CP_PARSER_ID_KIND_QUALIFIED CP_PARSER_ID_KIND_QUALIFIED
} cp_parser_id_kind; } cp_parser_id_kind;
/* The different kinds of declarators we want to parse. */
typedef enum cp_parser_declarator_kind
{
/* We want an abstract declartor. */
CP_PARSER_DECLARATOR_ABSTRACT,
/* We want a named declarator. */
CP_PARSER_DECLARATOR_NAMED,
/* We don't mind. */
CP_PARSER_DECLARATOR_EITHER
} cp_parser_declarator_kind;
/* A mapping from a token type to a corresponding tree node type. */ /* A mapping from a token type to a corresponding tree node type. */
typedef struct cp_parser_token_tree_map_node typedef struct cp_parser_token_tree_map_node
...@@ -1540,9 +1552,9 @@ static void cp_parser_linkage_specification ...@@ -1540,9 +1552,9 @@ static void cp_parser_linkage_specification
static tree cp_parser_init_declarator static tree cp_parser_init_declarator
PARAMS ((cp_parser *, tree, tree, tree, bool, bool, bool *)); PARAMS ((cp_parser *, tree, tree, tree, bool, bool, bool *));
static tree cp_parser_declarator static tree cp_parser_declarator
PARAMS ((cp_parser *, bool, bool *)); PARAMS ((cp_parser *, cp_parser_declarator_kind, bool *));
static tree cp_parser_direct_declarator static tree cp_parser_direct_declarator
PARAMS ((cp_parser *, bool, bool *)); PARAMS ((cp_parser *, cp_parser_declarator_kind, bool *));
static enum tree_code cp_parser_ptr_operator static enum tree_code cp_parser_ptr_operator
PARAMS ((cp_parser *, tree *, tree *)); PARAMS ((cp_parser *, tree *, tree *));
static tree cp_parser_cv_qualifier_seq_opt static tree cp_parser_cv_qualifier_seq_opt
...@@ -6123,8 +6135,7 @@ cp_parser_condition (parser) ...@@ -6123,8 +6135,7 @@ cp_parser_condition (parser)
tree initializer = NULL_TREE; tree initializer = NULL_TREE;
/* Parse the declarator. */ /* Parse the declarator. */
declarator = cp_parser_declarator (parser, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*abstract_p=*/false,
/*ctor_dtor_or_conv_p=*/NULL); /*ctor_dtor_or_conv_p=*/NULL);
/* Parse the attributes. */ /* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
...@@ -8506,8 +8517,7 @@ cp_parser_explicit_instantiation (parser) ...@@ -8506,8 +8517,7 @@ cp_parser_explicit_instantiation (parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*abstract_p=*/false,
/*ctor_dtor_or_conv_p=*/NULL); /*ctor_dtor_or_conv_p=*/NULL);
decl = grokdeclarator (declarator, decl_specifiers, decl = grokdeclarator (declarator, decl_specifiers,
NORMAL, 0, NULL); NORMAL, 0, NULL);
...@@ -9720,8 +9730,7 @@ cp_parser_init_declarator (parser, ...@@ -9720,8 +9730,7 @@ cp_parser_init_declarator (parser,
cp_parser_start_deferring_access_checks (parser); cp_parser_start_deferring_access_checks (parser);
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*abstract_p=*/false,
&ctor_dtor_or_conv_p); &ctor_dtor_or_conv_p);
/* Gather up the deferred checks. */ /* Gather up the deferred checks. */
declarator_access_checks declarator_access_checks
...@@ -10020,9 +10029,9 @@ cp_parser_init_declarator (parser, ...@@ -10020,9 +10029,9 @@ cp_parser_init_declarator (parser,
expression, not a declaration.) */ expression, not a declaration.) */
static tree static tree
cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p) cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p)
cp_parser *parser; cp_parser *parser;
bool abstract_p; cp_parser_declarator_kind dcl_kind;
bool *ctor_dtor_or_conv_p; bool *ctor_dtor_or_conv_p;
{ {
cp_token *token; cp_token *token;
...@@ -10054,16 +10063,17 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p) ...@@ -10054,16 +10063,17 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
{ {
/* 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 (abstract_p) if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
/* Parse the dependent declarator. */ /* Parse the dependent declarator. */
declarator = cp_parser_declarator (parser, abstract_p, declarator = cp_parser_declarator (parser, dcl_kind,
/*ctor_dtor_or_conv_p=*/NULL); /*ctor_dtor_or_conv_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. */
if (abstract_p && !cp_parser_parse_definitely (parser)) if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
&& !cp_parser_parse_definitely (parser))
declarator = NULL_TREE; declarator = NULL_TREE;
/* Build the representation of the ptr-operator. */ /* Build the representation of the ptr-operator. */
...@@ -10080,7 +10090,7 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p) ...@@ -10080,7 +10090,7 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
/* Everything else is a direct-declarator. */ /* Everything else is a direct-declarator. */
else else
declarator = cp_parser_direct_declarator (parser, declarator = cp_parser_direct_declarator (parser,
abstract_p, dcl_kind,
ctor_dtor_or_conv_p); ctor_dtor_or_conv_p);
if (attributes && declarator != error_mark_node) if (attributes && declarator != error_mark_node)
...@@ -10107,9 +10117,13 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p) ...@@ -10107,9 +10117,13 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
direct-abstract-declarator [opt] [ constant-expression [opt] ] direct-abstract-declarator [opt] [ constant-expression [opt] ]
( abstract-declarator ) ( abstract-declarator )
Returns a representation of the declarator. ABSTRACT_P is TRUE if Returns a representation of the declarator. DCL_KIND is
we are parsing a direct-abstract-declarator; FALSE if we are CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
parsing a direct-declarator. CTOR_DTOR_OR_CONV_P is as for direct-abstract-declarator. It is CP_PARSER_DECLARATOR_NAMED, if
we are parsing a direct-declarator. It is
CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
of ambiguity we prefer an abstract declarator, as per
[dcl.ambig.res]. CTOR_DTOR_OR_CONV_P is as for
cp_parser_declarator. cp_parser_declarator.
For the declarator-id production, the representation is as for an For the declarator-id production, the representation is as for an
...@@ -10122,164 +10136,147 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p) ...@@ -10122,164 +10136,147 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
indicating the size of the array is the second operand. */ indicating the size of the array is the second operand. */
static tree static tree
cp_parser_direct_declarator (parser, abstract_p, ctor_dtor_or_conv_p) cp_parser_direct_declarator (parser, dcl_kind, ctor_dtor_or_conv_p)
cp_parser *parser; cp_parser *parser;
bool abstract_p; cp_parser_declarator_kind dcl_kind;
bool *ctor_dtor_or_conv_p; bool *ctor_dtor_or_conv_p;
{ {
cp_token *token; cp_token *token;
tree declarator; tree declarator = NULL_TREE;
tree scope = NULL_TREE; tree scope = NULL_TREE;
bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_default_arg_ok_p = parser->default_arg_ok_p;
bool saved_in_declarator_p = parser->in_declarator_p; bool saved_in_declarator_p = parser->in_declarator_p;
bool first = true;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer); while (true)
/* Find the initial direct-declarator. It might be a parenthesized
declarator. */
if (token->type == CPP_OPEN_PAREN)
{
bool error_p;
/* For an abstract declarator we do not know whether we are
looking at the beginning of a parameter-declaration-clause,
or at a parenthesized abstract declarator. For example, if
we see `(int)', we are looking at a
parameter-declaration-clause, and the
direct-abstract-declarator has been omitted. If, on the
other hand we are looking at `((*))' then we are looking at a
parenthesized abstract-declarator. There is no easy way to
tell which situation we are in. */
if (abstract_p)
cp_parser_parse_tentatively (parser);
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
/* Parse the nested declarator. */
declarator
= cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p);
/* Expect a `)'. */
error_p = !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* If parsing a parenthesized abstract declarator didn't work,
try a parameter-declaration-clause. */
if (abstract_p && !cp_parser_parse_definitely (parser))
declarator = NULL_TREE;
/* If we were not parsing an abstract declarator, but failed to
find a satisfactory nested declarator, then an error has
occurred. */
else if (!abstract_p
&& (declarator == error_mark_node || error_p))
return error_mark_node;
/* Default args cannot appear in an abstract decl. */
parser->default_arg_ok_p = false;
}
/* Otherwise, for a non-abstract declarator, there should be a
declarator-id. */
else if (!abstract_p)
{ {
declarator = cp_parser_declarator_id (parser); /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
if (TREE_CODE (declarator) == SCOPE_REF) if (token->type == CPP_OPEN_PAREN)
{ {
scope = TREE_OPERAND (declarator, 0); /* This is either a parameter-declaration-clause, or a
parenthesized declarator. When we know we are parsing a
/* In the declaration of a member of a template class named declaratory, it must be a paranthesized declarator
outside of the class itself, the SCOPE will sometimes be if FIRST is true. For instance, `(int)' is a
a TYPENAME_TYPE. For example, given: parameter-declaration-clause, with an omitted
direct-abstract-declarator. But `((*))', is a
parenthesized abstract declarator. Finally, when T is a
template parameter `(T)' is a
paremeter-declaration-clause, and not a parenthesized
named declarator.
template <typename T> We first try and parse a parameter-declaration-clause,
int S<T>::R::i = 3; and then try a nested declarator (if FIRST is true).
the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In this
context, we must resolve S<T>::R to an ordinary type,
rather than a typename type.
The reason we normally avoid resolving TYPENAME_TYPEs is
that a specialization of `S' might render `S<T>::R' not a
type. However, if `S' is specialized, then this `i' will
not be used, so there is no harm in resolving the types
here. */
if (TREE_CODE (scope) == TYPENAME_TYPE)
{
/* Resolve the TYPENAME_TYPE. */
scope = cp_parser_resolve_typename_type (parser, scope);
/* If that failed, the declarator is invalid. */
if (scope == error_mark_node)
return error_mark_node;
/* Build a new DECLARATOR. */
declarator = build_nt (SCOPE_REF,
scope,
TREE_OPERAND (declarator, 1));
}
}
else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
/* Default args can only appear for a function decl. */
parser->default_arg_ok_p = false;
/* Check to see whether the declarator-id names a constructor,
destructor, or conversion. */
if (ctor_dtor_or_conv_p
&& ((TREE_CODE (declarator) == SCOPE_REF
&& CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
|| (TREE_CODE (declarator) != SCOPE_REF
&& at_class_scope_p ())))
{
tree unqualified_name;
tree class_type;
/* Get the unqualified part of the name. */ It is not an error for it not to be a
if (TREE_CODE (declarator) == SCOPE_REF) parameter-declaration-clause, even when FIRST is
{ false. Consider,
class_type = TREE_OPERAND (declarator, 0);
unqualified_name = TREE_OPERAND (declarator, 1); int i (int);
} int i (3);
else
The first is the declaration of a function while the
second is a the definition of a variable, including its
initializer.
Having seen only the parenthesis, we cannot know which of
these two alternatives should be selected. Even more
complex are examples like:
int i (int (a));
int i (int (3));
The former is a function-declaration; the latter is a
variable initialization.
Thus again, we try a parameter-declation-clause, and if
that fails, we back out and return. */
if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
{ {
class_type = current_class_type; tree params;
unqualified_name = declarator;
} cp_parser_parse_tentatively (parser);
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
if (first)
{
/* If this is going to be an abstract declarator, we're
in a declarator and we can't have default args. */
parser->default_arg_ok_p = false;
parser->in_declarator_p = true;
}
/* Parse the parameter-declaration-clause. */
params = cp_parser_parameter_declaration_clause (parser);
/* See if it names ctor, dtor or conv. */ /* If all went well, parse the cv-qualifier-seq and the
if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR exception-specfication. */
|| IDENTIFIER_TYPENAME_P (unqualified_name) if (cp_parser_parse_definitely (parser))
|| constructor_name_p (unqualified_name, class_type)) {
tree cv_qualifiers;
tree exception_specification;
first = false;
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
/* Parse the cv-qualifier-seq. */
cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
/* And the exception-specification. */
exception_specification
= cp_parser_exception_specification_opt (parser);
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
cv_qualifiers,
exception_specification);
/* Any subsequent parameter lists are to do with
return type, so are not those of the declared
function. */
parser->default_arg_ok_p = false;
/* Repeat the main loop. */
continue;
}
}
/* If this is the first, we can try a parenthesized
declarator. */
if (first)
{ {
*ctor_dtor_or_conv_p = true;
/* We would have cleared the default arg flag above, but
they are ok. */
parser->default_arg_ok_p = saved_default_arg_ok_p; parser->default_arg_ok_p = saved_default_arg_ok_p;
parser->in_declarator_p = saved_in_declarator_p;
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
/* Parse the nested declarator. */
declarator
= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p);
first = false;
/* Expect a `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
declarator = error_mark_node;
if (declarator == error_mark_node)
break;
goto handle_declarator;
} }
/* Otherwise, we must be done. */
else
break;
} }
} else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
/* But for an abstract declarator, the initial direct-declarator can && token->type == CPP_OPEN_SQUARE)
be omitted. */
else
{
declarator = NULL_TREE;
parser->default_arg_ok_p = false;
}
scope = get_scope_of_declarator (declarator);
if (scope)
/* Any names that appear after the declarator-id for a member
are looked up in the containing scope. */
push_scope (scope);
else
scope = NULL_TREE;
parser->in_declarator_p = true;
/* Now, parse function-declarators and array-declarators until there
are no more. */
while (true)
{
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* If it's a `[', we're looking at an array-declarator. */
if (token->type == CPP_OPEN_SQUARE)
{ {
/* Parse an array-declarator. */
tree bounds; tree bounds;
first = false;
parser->default_arg_ok_p = false;
parser->in_declarator_p = true;
/* Consume the `['. */ /* Consume the `['. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Peek at the next token. */ /* Peek at the next token. */
...@@ -10291,78 +10288,112 @@ cp_parser_direct_declarator (parser, abstract_p, ctor_dtor_or_conv_p) ...@@ -10291,78 +10288,112 @@ cp_parser_direct_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
else else
bounds = NULL_TREE; bounds = NULL_TREE;
/* Look for the closing `]'. */ /* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"); if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
{
declarator = error_mark_node;
break;
}
declarator = build_nt (ARRAY_REF, declarator, bounds); declarator = build_nt (ARRAY_REF, declarator, bounds);
} }
/* If it's a `(', we're looking at a function-declarator. */ else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
else if (token->type == CPP_OPEN_PAREN)
{ {
/* A function-declarator. Or maybe not. Consider, for /* Parse a declarator_id */
example: if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
cp_parser_parse_tentatively (parser);
int i (int); declarator = cp_parser_declarator_id (parser);
int i (3); if (dcl_kind == CP_PARSER_DECLARATOR_EITHER
&& !cp_parser_parse_definitely (parser))
The first is the declaration of a function while the declarator = error_mark_node;
second is a the definition of a variable, including its if (declarator == error_mark_node)
initializer. break;
Having seen only the parenthesis, we cannot know which of
these two alternatives should be selected. Even more
complex are examples like:
int i (int (a));
int i (int (3));
The former is a function-declaration; the latter is a
variable initialization.
First, we attempt to parse a parameter-declaration
clause. If this works, then we continue; otherwise, we
replace the tokens consumed in the process and continue. */
tree params;
/* We are now parsing tentatively. */
cp_parser_parse_tentatively (parser);
/* Consume the `('. */ if (TREE_CODE (declarator) == SCOPE_REF)
cp_lexer_consume_token (parser->lexer); {
/* Parse the parameter-declaration-clause. */ tree scope = TREE_OPERAND (declarator, 0);
params = cp_parser_parameter_declaration_clause (parser);
/* If all went well, parse the cv-qualifier-seq and the /* In the declaration of a member of a template class
exception-specification. */ outside of the class itself, the SCOPE will sometimes
if (cp_parser_parse_definitely (parser)) be a TYPENAME_TYPE. For example, given:
template <typename T>
int S<T>::R::i = 3;
the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
this context, we must resolve S<T>::R to an ordinary
type, rather than a typename type.
The reason we normally avoid resolving TYPENAME_TYPEs
is that a specialization of `S' might render
`S<T>::R' not a type. However, if `S' is
specialized, then this `i' will not be used, so there
is no harm in resolving the types here. */
if (TREE_CODE (scope) == TYPENAME_TYPE)
{
/* Resolve the TYPENAME_TYPE. */
scope = cp_parser_resolve_typename_type (parser, scope);
/* If that failed, the declarator is invalid. */
if (scope == error_mark_node)
return error_mark_node;
/* Build a new DECLARATOR. */
declarator = build_nt (SCOPE_REF,
scope,
TREE_OPERAND (declarator, 1));
}
}
/* Check to see whether the declarator-id names a constructor,
destructor, or conversion. */
if (declarator && ctor_dtor_or_conv_p
&& ((TREE_CODE (declarator) == SCOPE_REF
&& CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
|| (TREE_CODE (declarator) != SCOPE_REF
&& at_class_scope_p ())))
{ {
tree cv_qualifiers; tree unqualified_name;
tree exception_specification; tree class_type;
/* Consume the `)'. */ /* Get the unqualified part of the name. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); if (TREE_CODE (declarator) == SCOPE_REF)
{
/* Parse the cv-qualifier-seq. */ class_type = TREE_OPERAND (declarator, 0);
cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser); unqualified_name = TREE_OPERAND (declarator, 1);
/* And the exception-specification. */ }
exception_specification else
= cp_parser_exception_specification_opt (parser); {
class_type = current_class_type;
/* Create the function-declarator. */ unqualified_name = declarator;
declarator = make_call_declarator (declarator, }
params,
cv_qualifiers, /* See if it names ctor, dtor or conv. */
exception_specification); if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
|| IDENTIFIER_TYPENAME_P (unqualified_name)
|| constructor_name_p (unqualified_name, class_type))
*ctor_dtor_or_conv_p = true;
} }
/* Otherwise, we must be done with the declarator. */
handle_declarator:;
scope = get_scope_of_declarator (declarator);
if (scope)
/* Any names that appear after the declarator-id for a member
are looked up in the containing scope. */
push_scope (scope);
parser->in_declarator_p = true;
if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
|| (declarator
&& (TREE_CODE (declarator) == SCOPE_REF
|| TREE_CODE (declarator) == IDENTIFIER_NODE)))
/* Default args are only allowed on function
declarations. */
parser->default_arg_ok_p = saved_default_arg_ok_p;
else else
break; parser->default_arg_ok_p = false;
first = false;
} }
/* Otherwise, we're done with the declarator. */ /* We're done. */
else else
break; break;
/* Any subsequent parameter lists are to do with return type, so
are not those of the declared function. */
parser->default_arg_ok_p = false;
} }
/* For an abstract declarator, we might wind up with nothing at this /* For an abstract declarator, we might wind up with nothing at this
...@@ -10610,7 +10641,7 @@ cp_parser_type_id (parser) ...@@ -10610,7 +10641,7 @@ cp_parser_type_id (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, /*abstract_p=*/true, NULL); = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, 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;
...@@ -10911,23 +10942,15 @@ cp_parser_parameter_declaration (cp_parser *parser, ...@@ -10911,23 +10942,15 @@ cp_parser_parameter_declaration (cp_parser *parser,
bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_default_arg_ok_p = parser->default_arg_ok_p;
parser->default_arg_ok_p = false; parser->default_arg_ok_p = false;
/* We don't know whether the declarator will be abstract or
not. So, first we try an ordinary declarator. */
cp_parser_parse_tentatively (parser);
declarator = cp_parser_declarator (parser, declarator = cp_parser_declarator (parser,
/*abstract_p=*/false, CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL); /*ctor_dtor_or_conv_p=*/NULL);
/* If that didn't work, look for an abstract declarator. */
if (!cp_parser_parse_definitely (parser))
declarator = cp_parser_declarator (parser,
/*abstract_p=*/true,
/*ctor_dtor_or_conv_p=*/NULL);
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));
} }
/* The restriction on definining new types applies only to the type /* The restriction on defining new types applies only to the type
of the parameter, not to the default argument. */ of the parameter, not to the default argument. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
...@@ -11140,8 +11163,7 @@ cp_parser_function_definition (parser, friend_p) ...@@ -11140,8 +11163,7 @@ cp_parser_function_definition (parser, friend_p)
*friend_p = cp_parser_friend_p (decl_specifiers); *friend_p = cp_parser_friend_p (decl_specifiers);
/* Parse the declarator. */ /* Parse the declarator. */
declarator = cp_parser_declarator (parser, declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*abstract_p=*/false,
/*ctor_dtor_or_conv_p=*/NULL); /*ctor_dtor_or_conv_p=*/NULL);
/* Gather up any access checks that occurred. */ /* Gather up any access checks that occurred. */
...@@ -12314,8 +12336,7 @@ cp_parser_member_declaration (parser) ...@@ -12314,8 +12336,7 @@ cp_parser_member_declaration (parser)
/* Parse the declarator. */ /* Parse the declarator. */
declarator declarator
= cp_parser_declarator (parser, = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*abstract_p=*/false,
&ctor_dtor_or_conv_p); &ctor_dtor_or_conv_p);
/* If something went wrong parsing the declarator, make sure /* If something went wrong parsing the declarator, make sure
...@@ -12955,20 +12976,8 @@ cp_parser_exception_declaration (parser) ...@@ -12955,20 +12976,8 @@ cp_parser_exception_declaration (parser)
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
declarator = NULL_TREE; declarator = NULL_TREE;
else else
{ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
/* Otherwise, we can't be sure whether we are looking at a /*ctor_dtor_or_conv_p=*/NULL);
direct, or an abstract, declarator. */
cp_parser_parse_tentatively (parser);
/* Try an ordinary declarator. */
declarator = cp_parser_declarator (parser,
/*abstract_p=*/false,
/*ctor_dtor_or_conv_p=*/NULL);
/* If that didn't work, try an abstract declarator. */
if (!cp_parser_parse_definitely (parser))
declarator = cp_parser_declarator (parser,
/*abstract_p=*/true,
/*ctor_dtor_or_conv_p=*/NULL);
}
/* Restore the saved message. */ /* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
......
2003-01-06 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/parse/ambig1.C: New test.
* g++.dg/parse/defarg2.C: New test.
2003-01-05 Mark Mitchell <mark@codesourcery.com> 2003-01-05 Mark Mitchell <mark@codesourcery.com>
* g++.dg/template/defarg-1.C: New test. * g++.dg/template/defarg-1.C: New test.
......
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 4 Jan 2003 <nathan@codesourcery.com>
// PR 9109. Ambiguity. [dcl.ambig.res]/7
template <typename T> void Foo (int (T))
{
try {}
catch (int (T)) {}
}
// { dg-do compile }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 4 Jan 2003 <nathan@codesourcery.com>
// We erroneously prohibited default args on parenthesized function
// declarations.
void (foo)(int i = 0);
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