diff options
author | Mark Mitchell <mark@codesourcery.com> | 2005-04-08 21:13:57 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2005-04-08 21:13:57 +0000 |
commit | d4113656167b64f1c25138bbdf46d7f85ef1bd47 (patch) | |
tree | b7e912e2ceef8e6cf2a6d1ba9186e1ee98ce2282 | |
parent | 12af7ba340f80ef1222034ebe0ce88a4130a0462 (diff) | |
download | gcc-d4113656167b64f1c25138bbdf46d7f85ef1bd47.zip gcc-d4113656167b64f1c25138bbdf46d7f85ef1bd47.tar.gz gcc-d4113656167b64f1c25138bbdf46d7f85ef1bd47.tar.bz2 |
re PR c++/20905 (confuses unrelated type name with instance name)
PR c++/20905
* parser.c (cp_parser_type_specifier_seq): Add is_condition
parameter.
(cp_parser_new_type_id): Pass it.
(cp_parser_condition): Likewise.
(cp_parser_conversion_type_id): Likewise.
(cp_parser_type_id): Likewise.
(cp_parser_type_specifier_seq): In a condition, do not allow
invalid type-specifier combinations.
(cp_parser_exception_declaration): Adjust call to
cp_parser_type_specifier_seq.
PR c++/20905
* g++.dg/parse/cond2.C: New test.
From-SVN: r97857
-rw-r--r-- | gcc/cp/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/parser.c | 67 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/parse/cond2.C | 14 |
4 files changed, 78 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 145d490..50c1f0c 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,17 @@ 2005-04-08 Mark Mitchell <mark@codesourcery.com> + PR c++/20905 + * parser.c (cp_parser_type_specifier_seq): Add is_condition + parameter. + (cp_parser_new_type_id): Pass it. + (cp_parser_condition): Likewise. + (cp_parser_conversion_type_id): Likewise. + (cp_parser_type_id): Likewise. + (cp_parser_type_specifier_seq): In a condition, do not allow + invalid type-specifier combinations. + (cp_parser_exception_declaration): Adjust call to + cp_parser_type_specifier_seq. + * cp-tree.def (TINST_LEVEL): Document TINST_IN_SYSTEM_HEADER_P. * cp-tree.h (struct tinst_level): Add in_system_header_p. (TINST_IN_SYSTEM_HEADER_P): New macro. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index cb1623d6..8a11372 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1510,7 +1510,7 @@ static tree cp_parser_declarator_id static tree cp_parser_type_id (cp_parser *); static void cp_parser_type_specifier_seq - (cp_parser *, cp_decl_specifier_seq *); + (cp_parser *, bool, cp_decl_specifier_seq *); static cp_parameter_declarator *cp_parser_parameter_declaration_clause (cp_parser *); static cp_parameter_declarator *cp_parser_parameter_declaration_list @@ -4973,7 +4973,8 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts) parser->type_definition_forbidden_message = "types may not be defined in a new-type-id"; /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, &type_specifier_seq); + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifier_seq); /* Restore the old message. */ parser->type_definition_forbidden_message = saved_message; /* Parse the new-declarator. */ @@ -6305,7 +6306,8 @@ cp_parser_condition (cp_parser* parser) parser->type_definition_forbidden_message = "types may not be defined in conditions"; /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, &type_specifiers); + cp_parser_type_specifier_seq (parser, /*is_condition==*/true, + &type_specifiers); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; /* If all is well, we might be looking at a declaration. */ @@ -7564,7 +7566,8 @@ cp_parser_conversion_type_id (cp_parser* parser) /* Parse the attributes. */ attributes = cp_parser_attributes_opt (parser); /* Parse the type-specifiers. */ - cp_parser_type_specifier_seq (parser, &type_specifiers); + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifiers); /* If that didn't work, stop. */ if (type_specifiers.type == error_mark_node) return error_mark_node; @@ -11503,7 +11506,8 @@ cp_parser_type_id (cp_parser* parser) cp_declarator *abstract_declarator; /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, &type_specifier_seq); + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifier_seq); if (type_specifier_seq.type == error_mark_node) return error_mark_node; @@ -11531,13 +11535,18 @@ cp_parser_type_id (cp_parser* parser) type-specifier-seq: attributes type-specifier-seq [opt] + If IS_CONDITION is true, we are at the start of a "condition", + e.g., we've just seen "if (". + Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */ static void cp_parser_type_specifier_seq (cp_parser* parser, + bool is_condition, cp_decl_specifier_seq *type_specifier_seq) { bool seen_type_specifier = false; + cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL; /* Clear the TYPE_SPECIFIER_SEQ. */ clear_decl_specs (type_specifier_seq); @@ -11546,6 +11555,7 @@ cp_parser_type_specifier_seq (cp_parser* parser, while (true) { tree type_specifier; + bool is_cv_qualifier; /* Check for attributes first. */ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)) @@ -11558,25 +11568,45 @@ cp_parser_type_specifier_seq (cp_parser* parser, /* Look for the type-specifier. */ type_specifier = cp_parser_type_specifier (parser, - CP_PARSER_FLAGS_OPTIONAL, + flags, type_specifier_seq, /*is_declaration=*/false, NULL, - NULL); - /* If the first type-specifier could not be found, this is not a - type-specifier-seq at all. */ - if (!seen_type_specifier && !type_specifier) + &is_cv_qualifier); + if (!type_specifier) { - cp_parser_error (parser, "expected type-specifier"); - type_specifier_seq->type = error_mark_node; - return; + /* If the first type-specifier could not be found, this is not a + type-specifier-seq at all. */ + if (!seen_type_specifier) + { + cp_parser_error (parser, "expected type-specifier"); + type_specifier_seq->type = error_mark_node; + return; + } + /* If subsequent type-specifiers could not be found, the + type-specifier-seq is complete. */ + break; } - /* If subsequent type-specifiers could not be found, the - type-specifier-seq is complete. */ - else if (seen_type_specifier && !type_specifier) - break; seen_type_specifier = true; + /* The standard says that a condition can be: + + type-specifier-seq declarator = assignment-expression + + However, given: + + struct S {}; + if (int S = ...) + + we should treat the "S" as a declarator, not as a + type-specifier. The standard doesn't say that explicitly for + type-specifier-seq, but it does say that for + decl-specifier-seq in an ordinary declaration. Perhaps it + would be clearer just to allow a decl-specifier-seq here, and + then add a semantic restriction that if any decl-specifiers + that are not type-specifiers appear, the program is invalid. */ + if (is_condition && !is_cv_qualifier) + flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES; } return; @@ -13830,7 +13860,8 @@ cp_parser_exception_declaration (cp_parser* parser) = "types may not be defined in exception-declarations"; /* Parse the type-specifier-seq. */ - cp_parser_type_specifier_seq (parser, &type_specifiers); + cp_parser_type_specifier_seq (parser, /*is_condition=*/false, + &type_specifiers); /* If it's a `)', then there is no declarator. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)) declarator = NULL; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3ab4313..9d59bfc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2005-04-08 Mark Mitchell <mark@codesourcery.com> + PR c++/20905 + * g++.dg/parse/cond2.C: New test. + PR c++/20145 * g++.dg/warn/Wdtor1.C: New test. diff --git a/gcc/testsuite/g++.dg/parse/cond2.C b/gcc/testsuite/g++.dg/parse/cond2.C new file mode 100644 index 0000000..2dbe42b --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/cond2.C @@ -0,0 +1,14 @@ +// PR c++/20905 + +struct name {}; + +int +f (); + +void +g () +{ + if (int name = f ()) + { + } +} |