Commit 6c3f4949 by Jason Merrill Committed by Jason Merrill

re PR c++/38798 ([c++0x] Trouble with struct/class/enum keyword in late return types)

	PR c++/38798
	* parser.c (CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS): New.
	(cp_parser_type_specifier): Don't try to parse a class-specifier
	or enum-specifier in that case.
	(cp_parser_trailing_type_id): New.
	(cp_parser_late_return_type_opt): Call it.
	(cp_parser_type_id_1): Add is_trailing_return parm.
	(cp_parser_type_specifier_seq): Likewise.

From-SVN: r152924
parent f3dab3ba
2009-10-15 Jason Merrill <jason@redhat.com>
PR c++/38798
* parser.c (CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS): New.
(cp_parser_type_specifier): Don't try to parse a class-specifier
or enum-specifier in that case.
(cp_parser_trailing_type_id): New.
(cp_parser_late_return_type_opt): Call it.
(cp_parser_type_id_1): Add is_trailing_return parm.
(cp_parser_type_specifier_seq): Likewise.
2009-10-14 Jason Merrill <jason@redhat.com> 2009-10-14 Jason Merrill <jason@redhat.com>
PR c++/39866 PR c++/39866
......
...@@ -1194,8 +1194,12 @@ enum ...@@ -1194,8 +1194,12 @@ enum
/* The construct is optional. If it is not present, then no error /* The construct is optional. If it is not present, then no error
should be issued. */ should be issued. */
CP_PARSER_FLAGS_OPTIONAL = 0x1, CP_PARSER_FLAGS_OPTIONAL = 0x1,
/* When parsing a type-specifier, do not allow user-defined types. */ /* When parsing a type-specifier, treat user-defined type-names
CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2 as non-type identifiers. */
CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2,
/* When parsing a type-specifier, do not try to parse a class-specifier
or enum-specifier. */
CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4
}; };
/* This type is used for parameters and variables which hold /* This type is used for parameters and variables which hold
...@@ -1741,10 +1745,11 @@ static tree cp_parser_type_id ...@@ -1741,10 +1745,11 @@ static tree cp_parser_type_id
(cp_parser *); (cp_parser *);
static tree cp_parser_template_type_arg static tree cp_parser_template_type_arg
(cp_parser *); (cp_parser *);
static tree cp_parser_trailing_type_id (cp_parser *);
static tree cp_parser_type_id_1 static tree cp_parser_type_id_1
(cp_parser *, bool); (cp_parser *, bool, bool);
static void cp_parser_type_specifier_seq static void cp_parser_type_specifier_seq
(cp_parser *, bool, cp_decl_specifier_seq *); (cp_parser *, bool, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause static tree cp_parser_parameter_declaration_clause
(cp_parser *); (cp_parser *);
static tree cp_parser_parameter_declaration_list static tree cp_parser_parameter_declaration_list
...@@ -5795,6 +5800,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts) ...@@ -5795,6 +5800,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
= "types may not be defined in a new-type-id"; = "types may not be defined in a new-type-id";
/* Parse the type-specifier-seq. */ /* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
/*is_trailing_return=*/false,
&type_specifier_seq); &type_specifier_seq);
/* Restore the old message. */ /* Restore the old message. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
...@@ -8028,6 +8034,7 @@ cp_parser_condition (cp_parser* parser) ...@@ -8028,6 +8034,7 @@ cp_parser_condition (cp_parser* parser)
= "types may not be defined in conditions"; = "types may not be defined in conditions";
/* Parse the type-specifier-seq. */ /* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition==*/true, cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
/*is_trailing_return=*/false,
&type_specifiers); &type_specifiers);
/* Restore the saved message. */ /* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message; parser->type_definition_forbidden_message = saved_message;
...@@ -9669,6 +9676,7 @@ cp_parser_conversion_type_id (cp_parser* parser) ...@@ -9669,6 +9676,7 @@ cp_parser_conversion_type_id (cp_parser* parser)
attributes = cp_parser_attributes_opt (parser); attributes = cp_parser_attributes_opt (parser);
/* Parse the type-specifiers. */ /* Parse the type-specifiers. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
/*is_trailing_return=*/false,
&type_specifiers); &type_specifiers);
/* If that didn't work, stop. */ /* If that didn't work, stop. */
if (type_specifiers.type == error_mark_node) if (type_specifiers.type == error_mark_node)
...@@ -11644,6 +11652,9 @@ cp_parser_type_specifier (cp_parser* parser, ...@@ -11644,6 +11652,9 @@ cp_parser_type_specifier (cp_parser* parser,
switch (keyword) switch (keyword)
{ {
case RID_ENUM: case RID_ENUM:
if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
goto elaborated_type_specifier;
/* Look for the enum-specifier. */ /* Look for the enum-specifier. */
type_spec = cp_parser_enum_specifier (parser); type_spec = cp_parser_enum_specifier (parser);
/* If that worked, we're done. */ /* If that worked, we're done. */
...@@ -11666,6 +11677,9 @@ cp_parser_type_specifier (cp_parser* parser, ...@@ -11666,6 +11677,9 @@ cp_parser_type_specifier (cp_parser* parser,
case RID_CLASS: case RID_CLASS:
case RID_STRUCT: case RID_STRUCT:
case RID_UNION: case RID_UNION:
if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
goto elaborated_type_specifier;
/* Parse tentatively so that we can back up if we don't find a /* Parse tentatively so that we can back up if we don't find a
class-specifier. */ class-specifier. */
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
...@@ -12532,6 +12546,7 @@ cp_parser_enum_specifier (cp_parser* parser) ...@@ -12532,6 +12546,7 @@ cp_parser_enum_specifier (cp_parser* parser)
/* Parse the type-specifier-seq. */ /* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
/*is_trailing_return=*/false,
&type_specifiers); &type_specifiers);
/* At this point this is surely not elaborated type specifier. */ /* At this point this is surely not elaborated type specifier. */
...@@ -14422,7 +14437,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser) ...@@ -14422,7 +14437,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
/* Parse a late-specified return type, if any. This is not a separate /* Parse a late-specified return type, if any. This is not a separate
non-terminal, but part of a function declarator, which looks like non-terminal, but part of a function declarator, which looks like
-> type-id -> trailing-type-specifier-seq abstract-declarator(opt)
Returns the type indicated by the type-id. */ Returns the type indicated by the type-id. */
...@@ -14440,7 +14455,7 @@ cp_parser_late_return_type_opt (cp_parser* parser) ...@@ -14440,7 +14455,7 @@ cp_parser_late_return_type_opt (cp_parser* parser)
/* Consume the ->. */ /* Consume the ->. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
return cp_parser_type_id (parser); return cp_parser_trailing_type_id (parser);
} }
/* Parse a declarator-id. /* Parse a declarator-id.
...@@ -14493,13 +14508,15 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p) ...@@ -14493,13 +14508,15 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
Returns the TYPE specified. */ Returns the TYPE specified. */
static tree static tree
cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg) cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
bool is_trailing_return)
{ {
cp_decl_specifier_seq type_specifier_seq; cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator; cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */ /* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
is_trailing_return,
&type_specifier_seq); &type_specifier_seq);
if (type_specifier_seq.type == error_mark_node) if (type_specifier_seq.type == error_mark_node)
return error_mark_node; return error_mark_node;
...@@ -14537,12 +14554,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg) ...@@ -14537,12 +14554,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
static tree cp_parser_type_id (cp_parser *parser) static tree cp_parser_type_id (cp_parser *parser)
{ {
return cp_parser_type_id_1 (parser, false); return cp_parser_type_id_1 (parser, false, false);
} }
static tree cp_parser_template_type_arg (cp_parser *parser) static tree cp_parser_template_type_arg (cp_parser *parser)
{ {
return cp_parser_type_id_1 (parser, true); return cp_parser_type_id_1 (parser, true, false);
}
static tree cp_parser_trailing_type_id (cp_parser *parser)
{
return cp_parser_type_id_1 (parser, false, true);
} }
/* Parse a type-specifier-seq. /* Parse a type-specifier-seq.
...@@ -14558,11 +14580,15 @@ static tree cp_parser_template_type_arg (cp_parser *parser) ...@@ -14558,11 +14580,15 @@ static tree cp_parser_template_type_arg (cp_parser *parser)
If IS_CONDITION is true, we are at the start of a "condition", If IS_CONDITION is true, we are at the start of a "condition",
e.g., we've just seen "if (". e.g., we've just seen "if (".
If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
i.e. we've just seen "->".
Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */ Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */
static void static void
cp_parser_type_specifier_seq (cp_parser* parser, cp_parser_type_specifier_seq (cp_parser* parser,
bool is_condition, bool is_condition,
bool is_trailing_return,
cp_decl_specifier_seq *type_specifier_seq) cp_decl_specifier_seq *type_specifier_seq)
{ {
bool seen_type_specifier = false; bool seen_type_specifier = false;
...@@ -14572,6 +14598,12 @@ cp_parser_type_specifier_seq (cp_parser* parser, ...@@ -14572,6 +14598,12 @@ cp_parser_type_specifier_seq (cp_parser* parser,
/* Clear the TYPE_SPECIFIER_SEQ. */ /* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq); clear_decl_specs (type_specifier_seq);
/* In the context of a trailing return type, enum E { } is an
elaborated-type-specifier followed by a function-body, not an
enum-specifier. */
if (is_trailing_return)
flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
/* Parse the type-specifiers and attributes. */ /* Parse the type-specifiers and attributes. */
while (true) while (true)
{ {
...@@ -17283,6 +17315,7 @@ cp_parser_exception_declaration (cp_parser* parser) ...@@ -17283,6 +17315,7 @@ cp_parser_exception_declaration (cp_parser* parser)
/* Parse the type-specifier-seq. */ /* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
/*is_trailing_return=*/false,
&type_specifiers); &type_specifiers);
/* If it's a `)', then there is no declarator. */ /* If it's a `)', then there is no declarator. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
...@@ -22056,6 +22089,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses) ...@@ -22056,6 +22089,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
cp_parser_parse_tentatively (parser); cp_parser_parse_tentatively (parser);
cp_parser_type_specifier_seq (parser, /*is_condition=*/false, cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
/*is_trailing_return=*/false,
&type_specifiers); &type_specifiers);
if (cp_parser_parse_definitely (parser)) if (cp_parser_parse_definitely (parser))
{ {
......
2009-10-15 Jason Merrill <jason@redhat.com>
PR c++/38798
* g++.dg/cpp0x/trailing5.C: New.
2009-10-16 Janus Weil <janus@gcc.gnu.org> 2009-10-16 Janus Weil <janus@gcc.gnu.org>
PR fortran/41719 PR fortran/41719
......
// PR c++/38798, DR 770
// { dg-options -std=c++0x }
struct A {};
auto foo() -> struct A {}
enum B {};
auto bar() -> enum B {}
auto baz() -> struct C {} {} // { 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