diff options
author | Jason Merrill <jason@redhat.com> | 2009-10-17 02:11:08 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-10-17 02:11:08 -0400 |
commit | 6c3f4949eeda138f5ffa0377443d626951ecc0a7 (patch) | |
tree | 9b15630abf437c27a20a3a76ca381a953f3d6109 /gcc | |
parent | f3dab3bade514a8bc1da85da5b19fc482e275864 (diff) | |
download | gcc-6c3f4949eeda138f5ffa0377443d626951ecc0a7.zip gcc-6c3f4949eeda138f5ffa0377443d626951ecc0a7.tar.gz gcc-6c3f4949eeda138f5ffa0377443d626951ecc0a7.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/parser.c | 52 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing1.C (renamed from gcc/testsuite/g++.dg/cpp0x/auto6.C) | 0 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing2.C (renamed from gcc/testsuite/g++.dg/cpp0x/auto8.C) | 0 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing3.C (renamed from gcc/testsuite/g++.dg/cpp0x/auto12.C) | 0 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing4.C (renamed from gcc/testsuite/g++.dg/cpp0x/auto13.C) | 0 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/trailing5.C | 10 |
8 files changed, 69 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d36aea5..d842d8e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +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> PR c++/39866 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 5e37343..b9b53e5 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1194,8 +1194,12 @@ enum /* The construct is optional. If it is not present, then no error should be issued. */ CP_PARSER_FLAGS_OPTIONAL = 0x1, - /* When parsing a type-specifier, do not allow user-defined types. */ - CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2 + /* When parsing a type-specifier, treat user-defined type-names + 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 @@ -1741,10 +1745,11 @@ static tree cp_parser_type_id (cp_parser *); static tree cp_parser_template_type_arg (cp_parser *); +static tree cp_parser_trailing_type_id (cp_parser *); static tree cp_parser_type_id_1 - (cp_parser *, bool); + (cp_parser *, bool, bool); 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 (cp_parser *); static tree cp_parser_parameter_declaration_list @@ -5795,6 +5800,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts) = "types may not be defined in a new-type-id"; /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + /*is_trailing_return=*/false, &type_specifier_seq); /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; @@ -8028,6 +8034,7 @@ cp_parser_condition (cp_parser* parser) = "types may not be defined in conditions"; /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, /*is_condition==*/true, + /*is_trailing_return=*/false, &type_specifiers); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; @@ -9669,6 +9676,7 @@ cp_parser_conversion_type_id (cp_parser* parser) attributes = cp_parser_attributes_opt (parser); /* Parse the type-specifiers. */ cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + /*is_trailing_return=*/false, &type_specifiers); /* If that didn't work, stop. */ if (type_specifiers.type == error_mark_node) @@ -11644,6 +11652,9 @@ cp_parser_type_specifier (cp_parser* parser, switch (keyword) { case RID_ENUM: + if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS)) + goto elaborated_type_specifier; + /* Look for the enum-specifier. */ type_spec = cp_parser_enum_specifier (parser); /* If that worked, we're done. */ @@ -11666,6 +11677,9 @@ cp_parser_type_specifier (cp_parser* parser, case RID_CLASS: case RID_STRUCT: 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 class-specifier. */ cp_parser_parse_tentatively (parser); @@ -12532,6 +12546,7 @@ cp_parser_enum_specifier (cp_parser* parser) /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + /*is_trailing_return=*/false, &type_specifiers); /* At this point this is surely not elaborated type specifier. */ @@ -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 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. */ @@ -14440,7 +14455,7 @@ cp_parser_late_return_type_opt (cp_parser* parser) /* Consume the ->. */ cp_lexer_consume_token (parser->lexer); - return cp_parser_type_id (parser); + return cp_parser_trailing_type_id (parser); } /* Parse a declarator-id. @@ -14493,13 +14508,15 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p) Returns the TYPE specified. */ 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_declarator *abstract_declarator; /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + is_trailing_return, &type_specifier_seq); if (type_specifier_seq.type == error_mark_node) return error_mark_node; @@ -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) { - 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) { - 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. @@ -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", 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. */ static void cp_parser_type_specifier_seq (cp_parser* parser, bool is_condition, + bool is_trailing_return, cp_decl_specifier_seq *type_specifier_seq) { bool seen_type_specifier = false; @@ -14572,6 +14598,12 @@ cp_parser_type_specifier_seq (cp_parser* parser, /* Clear the 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. */ while (true) { @@ -17283,6 +17315,7 @@ cp_parser_exception_declaration (cp_parser* parser) /* Parse the type-specifier-seq. */ cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + /*is_trailing_return=*/false, &type_specifiers); /* If it's a `)', then there is no declarator. */ 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) cp_parser_parse_tentatively (parser); cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + /*is_trailing_return=*/false, &type_specifiers); if (cp_parser_parse_definitely (parser)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ffd0d7e..8970e1c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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> PR fortran/41719 diff --git a/gcc/testsuite/g++.dg/cpp0x/auto6.C b/gcc/testsuite/g++.dg/cpp0x/trailing1.C index 11e73d2..11e73d2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto6.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing1.C diff --git a/gcc/testsuite/g++.dg/cpp0x/auto8.C b/gcc/testsuite/g++.dg/cpp0x/trailing2.C index e45204f..e45204f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto8.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing2.C diff --git a/gcc/testsuite/g++.dg/cpp0x/auto12.C b/gcc/testsuite/g++.dg/cpp0x/trailing3.C index 82d36f0..82d36f0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto12.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing3.C diff --git a/gcc/testsuite/g++.dg/cpp0x/auto13.C b/gcc/testsuite/g++.dg/cpp0x/trailing4.C index dc7e35a..dc7e35a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto13.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing4.C diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing5.C b/gcc/testsuite/g++.dg/cpp0x/trailing5.C new file mode 100644 index 0000000..b97d362 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/trailing5.C @@ -0,0 +1,10 @@ +// 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 "" } |