aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-01-06 18:40:22 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-01-06 18:40:22 +0000
commit62b8a44e2617685f1094b108869f2c71f38f33af (patch)
tree649fe3bdf8170a387fdf89fd878e30bb2641d027 /gcc
parente914a571723bd02ba7236eacbbc97a4c5d80bce0 (diff)
downloadgcc-62b8a44e2617685f1094b108869f2c71f38f33af.zip
gcc-62b8a44e2617685f1094b108869f2c71f38f33af.tar.gz
gcc-62b8a44e2617685f1094b108869f2c71f38f33af.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog18
-rw-r--r--gcc/cp/parser.c497
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/parse/ambig1.C12
-rw-r--r--gcc/testsuite/g++.dg/parse/defarg2.C9
5 files changed, 297 insertions, 244 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 0da8e47..d4284a5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,21 @@
+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>
* parser.c (cp_parser_template_parameter): Adjust call to
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 02bcd4d..d1c2c30 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1124,6 +1124,18 @@ typedef enum cp_parser_id_kind
CP_PARSER_ID_KIND_QUALIFIED
} 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. */
typedef struct cp_parser_token_tree_map_node
@@ -1540,9 +1552,9 @@ static void cp_parser_linkage_specification
static tree cp_parser_init_declarator
PARAMS ((cp_parser *, tree, tree, tree, bool, bool, bool *));
static tree cp_parser_declarator
- PARAMS ((cp_parser *, bool, bool *));
+ PARAMS ((cp_parser *, cp_parser_declarator_kind, bool *));
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
PARAMS ((cp_parser *, tree *, tree *));
static tree cp_parser_cv_qualifier_seq_opt
@@ -6123,8 +6135,7 @@ cp_parser_condition (parser)
tree initializer = NULL_TREE;
/* Parse the declarator. */
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
@@ -8506,8 +8517,7 @@ cp_parser_explicit_instantiation (parser)
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
decl = grokdeclarator (declarator, decl_specifiers,
NORMAL, 0, NULL);
@@ -9720,8 +9730,7 @@ cp_parser_init_declarator (parser,
cp_parser_start_deferring_access_checks (parser);
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p);
/* Gather up the deferred checks. */
declarator_access_checks
@@ -10020,9 +10029,9 @@ cp_parser_init_declarator (parser,
expression, not a declaration.) */
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;
- bool abstract_p;
+ cp_parser_declarator_kind dcl_kind;
bool *ctor_dtor_or_conv_p;
{
cp_token *token;
@@ -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
abstract-declarator. */
- if (abstract_p)
+ if (dcl_kind != CP_PARSER_DECLARATOR_NAMED)
cp_parser_parse_tentatively (parser);
/* Parse the dependent declarator. */
- declarator = cp_parser_declarator (parser, abstract_p,
+ declarator = cp_parser_declarator (parser, dcl_kind,
/*ctor_dtor_or_conv_p=*/NULL);
/* If we are parsing an abstract-declarator, we must handle the
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;
/* Build the representation of the ptr-operator. */
@@ -10080,7 +10090,7 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
/* Everything else is a direct-declarator. */
else
declarator = cp_parser_direct_declarator (parser,
- abstract_p,
+ dcl_kind,
ctor_dtor_or_conv_p);
if (attributes && declarator != error_mark_node)
@@ -10107,9 +10117,13 @@ cp_parser_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
direct-abstract-declarator [opt] [ constant-expression [opt] ]
( abstract-declarator )
- Returns a representation of the declarator. ABSTRACT_P is TRUE if
- we are parsing a direct-abstract-declarator; FALSE if we are
- parsing a direct-declarator. CTOR_DTOR_OR_CONV_P is as for
+ Returns a representation of the declarator. DCL_KIND is
+ CP_PARSER_DECLARATOR_ABSTRACT, if we are parsing a
+ 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.
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)
indicating the size of the array is the second operand. */
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;
- bool abstract_p;
+ cp_parser_declarator_kind dcl_kind;
bool *ctor_dtor_or_conv_p;
{
cp_token *token;
- tree declarator;
+ tree declarator = NULL_TREE;
tree scope = NULL_TREE;
bool saved_default_arg_ok_p = parser->default_arg_ok_p;
bool saved_in_declarator_p = parser->in_declarator_p;
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* 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)
+ bool first = true;
+
+ while (true)
{
- declarator = cp_parser_declarator_id (parser);
-
- if (TREE_CODE (declarator) == SCOPE_REF)
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_OPEN_PAREN)
{
- scope = TREE_OPERAND (declarator, 0);
-
- /* In the declaration of a member of a template class
- outside of the class itself, the SCOPE will sometimes be
- a TYPENAME_TYPE. For example, given:
+ /* This is either a parameter-declaration-clause, or a
+ parenthesized declarator. When we know we are parsing a
+ named declaratory, it must be a paranthesized declarator
+ if FIRST is true. For instance, `(int)' is a
+ 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>
- 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));
- }
- }
- 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;
+ We first try and parse a parameter-declaration-clause,
+ and then try a nested declarator (if FIRST is true).
- /* Get the unqualified part of the name. */
- if (TREE_CODE (declarator) == SCOPE_REF)
- {
- class_type = TREE_OPERAND (declarator, 0);
- unqualified_name = TREE_OPERAND (declarator, 1);
- }
- else
+ It is not an error for it not to be a
+ parameter-declaration-clause, even when FIRST is
+ false. Consider,
+
+ int i (int);
+ int i (3);
+
+ 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;
- unqualified_name = declarator;
- }
+ tree params;
+
+ 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 (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
- || IDENTIFIER_TYPENAME_P (unqualified_name)
- || constructor_name_p (unqualified_name, class_type))
+ /* If all went well, parse the cv-qualifier-seq and the
+ exception-specfication. */
+ if (cp_parser_parse_definitely (parser))
+ {
+ 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->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;
}
- }
- /* But for an abstract declarator, the initial direct-declarator can
- 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)
+ else if ((!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
+ && token->type == CPP_OPEN_SQUARE)
{
+ /* Parse an array-declarator. */
tree bounds;
+ first = false;
+ parser->default_arg_ok_p = false;
+ parser->in_declarator_p = true;
/* Consume the `['. */
cp_lexer_consume_token (parser->lexer);
/* Peek at the next token. */
@@ -10291,78 +10288,112 @@ cp_parser_direct_declarator (parser, abstract_p, ctor_dtor_or_conv_p)
else
bounds = NULL_TREE;
/* 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);
}
- /* If it's a `(', we're looking at a function-declarator. */
- else if (token->type == CPP_OPEN_PAREN)
+ else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
- /* A function-declarator. Or maybe not. Consider, for
- example:
-
- int i (int);
- int i (3);
-
- 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.
-
- 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);
+ /* Parse a declarator_id */
+ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+ cp_parser_parse_tentatively (parser);
+ declarator = cp_parser_declarator_id (parser);
+ if (dcl_kind == CP_PARSER_DECLARATOR_EITHER
+ && !cp_parser_parse_definitely (parser))
+ declarator = error_mark_node;
+ if (declarator == error_mark_node)
+ break;
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the parameter-declaration-clause. */
- params = cp_parser_parameter_declaration_clause (parser);
+ if (TREE_CODE (declarator) == SCOPE_REF)
+ {
+ tree scope = TREE_OPERAND (declarator, 0);
- /* If all went well, parse the cv-qualifier-seq and the
- exception-specification. */
- if (cp_parser_parse_definitely (parser))
+ /* In the declaration of a member of a template class
+ outside of the class itself, the SCOPE will sometimes
+ 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 exception_specification;
-
- /* 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);
+ tree unqualified_name;
+ tree class_type;
+
+ /* Get the unqualified part of the name. */
+ if (TREE_CODE (declarator) == SCOPE_REF)
+ {
+ class_type = TREE_OPERAND (declarator, 0);
+ unqualified_name = TREE_OPERAND (declarator, 1);
+ }
+ else
+ {
+ class_type = current_class_type;
+ unqualified_name = declarator;
+ }
+
+ /* See if it names ctor, dtor or conv. */
+ 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
- break;
+ parser->default_arg_ok_p = false;
+
+ first = false;
}
- /* Otherwise, we're done with the declarator. */
+ /* We're done. */
else
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
@@ -10610,7 +10641,7 @@ cp_parser_type_id (parser)
cp_parser_parse_tentatively (parser);
/* Look for the 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. */
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL_TREE;
@@ -10911,23 +10942,15 @@ cp_parser_parameter_declaration (cp_parser *parser,
bool saved_default_arg_ok_p = parser->default_arg_ok_p;
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,
- /*abstract_p=*/false,
+ CP_PARSER_DECLARATOR_EITHER,
/*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;
/* After the declarator, allow more attributes. */
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. */
parser->type_definition_forbidden_message = saved_message;
@@ -11140,8 +11163,7 @@ cp_parser_function_definition (parser, friend_p)
*friend_p = cp_parser_friend_p (decl_specifiers);
/* Parse the declarator. */
- declarator = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL);
/* Gather up any access checks that occurred. */
@@ -12314,8 +12336,7 @@ cp_parser_member_declaration (parser)
/* Parse the declarator. */
declarator
- = cp_parser_declarator (parser,
- /*abstract_p=*/false,
+ = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p);
/* If something went wrong parsing the declarator, make sure
@@ -12955,20 +12976,8 @@ cp_parser_exception_declaration (parser)
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
declarator = NULL_TREE;
else
- {
- /* Otherwise, we can't be sure whether we are looking at a
- 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);
- }
+ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
+ /*ctor_dtor_or_conv_p=*/NULL);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b81e6aa..c6c0cd0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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>
* g++.dg/template/defarg-1.C: New test.
diff --git a/gcc/testsuite/g++.dg/parse/ambig1.C b/gcc/testsuite/g++.dg/parse/ambig1.C
new file mode 100644
index 0000000..2645879
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/ambig1.C
@@ -0,0 +1,12 @@
+// { 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)) {}
+}
diff --git a/gcc/testsuite/g++.dg/parse/defarg2.C b/gcc/testsuite/g++.dg/parse/defarg2.C
new file mode 100644
index 0000000..571855a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/defarg2.C
@@ -0,0 +1,9 @@
+// { 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);