From 782d1c333f42c650699be7f7f4679c38ab544ecd Mon Sep 17 00:00:00 2001 From: Nathan Froyd Date: Thu, 16 Dec 2010 01:36:09 +0000 Subject: [PATCH] re PR c++/39859 (duplicated and unhelpful error for "c:n" (parser)) gcc/cp/ PR c++/39859 PR c++/44522 PR c++/44523 * parser.c (struct cp_parser): Add colon_corrects_to_scope_p field. (cp_parser_new): Initialize it. (cp_parser_nested_name_specifier_opt): Auto-correct colons to scopes if we are able to. (cp_parser_question_colon_clause): Disallow colon correction. (cp_parser_label_for_labeled_statement): Likewise. (cp_parser_range_for): Likewise. (cp_parser_enum_specifier): Likewise. (cp_parser_class_head): Likewise. (cp_parser_member_declaration): Likewise. gcc/testsuite/ PR c++/39859 PR c++/44522 PR c++/44523 * g++.dg/parse/colon-autocorrect-1.C: New testcase. * g++.dg/parse/colon-autocorrect-2.C: New testcase. From-SVN: r167895 --- gcc/cp/ChangeLog | 16 ++++++ gcc/cp/parser.c | 73 ++++++++++++++++++++---- gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/g++.dg/parse/colon-autocorrect-1.C | 31 ++++++++++ gcc/testsuite/g++.dg/parse/colon-autocorrect-2.C | 15 +++++ 5 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/colon-autocorrect-1.C create mode 100644 gcc/testsuite/g++.dg/parse/colon-autocorrect-2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e6a9610..0d46bcc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,21 @@ 2010-12-15 Nathan Froyd + PR c++/39859 + PR c++/44522 + PR c++/44523 + * parser.c (struct cp_parser): Add colon_corrects_to_scope_p field. + (cp_parser_new): Initialize it. + (cp_parser_nested_name_specifier_opt): Auto-correct colons to + scopes if we are able to. + (cp_parser_question_colon_clause): Disallow colon correction. + (cp_parser_label_for_labeled_statement): Likewise. + (cp_parser_range_for): Likewise. + (cp_parser_enum_specifier): Likewise. + (cp_parser_class_head): Likewise. + (cp_parser_member_declaration): Likewise. + +2010-12-15 Nathan Froyd + PR c++/46852 * parser.c (cp_parser_class_specifier): Check for TYPE_P. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index cb8b797..3e6930f 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1700,6 +1700,9 @@ typedef struct GTY(()) cp_parser { a local class. */ bool in_function_body; + /* TRUE if we can auto-correct a colon to a scope operator. */ + bool colon_corrects_to_scope_p; + /* If non-NULL, then we are parsing a construct where new type definitions are not permitted. The string stored here will be issued as an error message if a type is defined. */ @@ -3244,6 +3247,9 @@ cp_parser_new (void) /* We are not parsing a function body. */ parser->in_function_body = false; + /* We can correct until told otherwise. */ + parser->colon_corrects_to_scope_p = true; + /* The unparsed function queue is empty. */ push_unparsed_function_queues (parser); @@ -4553,6 +4559,16 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser, template-id), nor a `::', then we are not looking at a nested-name-specifier. */ token = cp_lexer_peek_nth_token (parser->lexer, 2); + + if (token->type == CPP_COLON + && parser->colon_corrects_to_scope_p + && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_NAME) + { + error_at (token->location, + "found %<:%> in nested-name-specifier, expected %<::%>"); + token->type = CPP_SCOPE; + } + if (token->type != CPP_SCOPE && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2)) @@ -6955,12 +6971,15 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr) } else { + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + parser->colon_corrects_to_scope_p = false; /* Parse the expression. */ c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node; expr = cp_parser_expression (parser, /*cast_p=*/false, NULL); c_inhibit_evaluation_warnings += ((logical_or_expr == truthvalue_true_node) - (logical_or_expr == truthvalue_false_node)); + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } /* The next token should be a `:'. */ @@ -8153,6 +8172,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) { cp_token *token; tree label = NULL_TREE; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; /* The next token should be an identifier. */ token = cp_lexer_peek_token (parser->lexer); @@ -8163,6 +8183,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) return; } + parser->colon_corrects_to_scope_p = false; switch (token->keyword) { case RID_CASE: @@ -8241,6 +8262,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser) else cplus_decl_attributes (&label, attrs, 0); } + + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } /* Parse an expression-statement. @@ -8710,7 +8733,9 @@ cp_parser_range_for (cp_parser *parser) cp_declarator *declarator; const char *saved_message; tree attributes, pushed_scope; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + parser->colon_corrects_to_scope_p = false; cp_parser_parse_tentatively (parser); /* New types are not allowed in the type-specifier-seq for a range-based for loop. */ @@ -8727,7 +8752,8 @@ cp_parser_range_for (cp_parser *parser) if (cp_parser_error_occurred (parser)) { cp_parser_abort_tentative_parse (parser); - return NULL_TREE; + stmt = NULL_TREE; + goto out; } /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, @@ -8774,6 +8800,8 @@ cp_parser_range_for (cp_parser *parser) /* Convert the range-based for loop into a normal for-statement. */ stmt = cp_convert_range_for (stmt, range_decl, range_expr); + out: + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return stmt; } @@ -13343,6 +13371,9 @@ cp_parser_enum_specifier (cp_parser* parser) bool is_anonymous = false; tree underlying_type = NULL_TREE; cp_token *type_start_token = NULL; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + + parser->colon_corrects_to_scope_p = false; /* Parse tentatively so that we can back up if we don't find a enum-specifier. */ @@ -13470,7 +13501,10 @@ cp_parser_enum_specifier (cp_parser* parser) { cp_parser_error (parser, "expected %<{%>"); if (has_underlying_type) - return NULL_TREE; + { + type = NULL_TREE; + goto out; + } } /* An opaque-enum-specifier must have a ';' here. */ if ((scoped_enum_p || underlying_type) @@ -13478,7 +13512,10 @@ cp_parser_enum_specifier (cp_parser* parser) { cp_parser_error (parser, "expected %<;%> or %<{%>"); if (has_underlying_type) - return NULL_TREE; + { + type = NULL_TREE; + goto out; + } } } @@ -13622,6 +13659,8 @@ cp_parser_enum_specifier (cp_parser* parser) pop_nested_namespace (nested_name_specifier); } } + out: + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return type; } @@ -17087,6 +17126,7 @@ cp_parser_class_head (cp_parser* parser, bool qualified_p = false; bool invalid_nested_name_p = false; bool invalid_explicit_specialization_p = false; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; tree pushed_scope = NULL_TREE; unsigned num_templates; cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL; @@ -17095,6 +17135,7 @@ cp_parser_class_head (cp_parser* parser, /* Assume no template parameter lists will be used in defining the type. */ num_templates = 0; + parser->colon_corrects_to_scope_p = false; *bases = NULL_TREE; @@ -17234,7 +17275,8 @@ cp_parser_class_head (cp_parser* parser, if (!cp_parser_next_token_starts_class_definition_p (parser)) { cp_parser_error (parser, "expected %<{%> or %<:%>"); - return error_mark_node; + type = error_mark_node; + goto out; } /* At this point, we're going ahead with the class-specifier, even @@ -17245,13 +17287,15 @@ cp_parser_class_head (cp_parser* parser, { cp_parser_error (parser, "global qualification of class name is invalid"); - return error_mark_node; + type = error_mark_node; + goto out; } else if (invalid_nested_name_p) { cp_parser_error (parser, "qualified name does not name a class"); - return error_mark_node; + type = error_mark_node; + goto out; } else if (nested_name_specifier) { @@ -17454,6 +17498,8 @@ cp_parser_class_head (cp_parser* parser, if (type) DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location; *attributes_p = attributes; + out: + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; return type; } @@ -17582,6 +17628,7 @@ cp_parser_member_declaration (cp_parser* parser) cp_token *decl_spec_token_start = NULL; cp_token *initializer_token_start = NULL; int saved_pedantic; + bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; /* Check for the `__extension__' keyword. */ if (cp_parser_extension_opt (parser, &saved_pedantic)) @@ -17640,8 +17687,10 @@ cp_parser_member_declaration (cp_parser* parser) return; } + parser->colon_corrects_to_scope_p = false; + if (cp_parser_using_declaration (parser, /*access_declaration=*/true)) - return; + goto out; /* Parse the decl-specifier-seq. */ decl_spec_token_start = cp_lexer_peek_token (parser->lexer); @@ -17654,7 +17703,7 @@ cp_parser_member_declaration (cp_parser* parser) /* Check for an invalid type-name. */ if (!decl_specifiers.any_type_specifiers_p && cp_parser_parse_and_diagnose_invalid_type_name (parser)) - return; + goto out; /* If there is no declarator, then the decl-specifier-seq should specify a type. */ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) @@ -17824,7 +17873,7 @@ cp_parser_member_declaration (cp_parser* parser) if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)) cp_lexer_consume_token (parser->lexer); - return; + goto out; } if (declares_class_or_enum & 2) @@ -17903,7 +17952,7 @@ cp_parser_member_declaration (cp_parser* parser) /* If the next token is a semicolon, consume it. */ if (token->type == CPP_SEMICOLON) cp_lexer_consume_token (parser->lexer); - return; + goto out; } else if (declarator->kind == cdk_function) @@ -17958,11 +18007,13 @@ cp_parser_member_declaration (cp_parser* parser) } if (assume_semicolon) - return; + goto out; } } cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); + out: + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; } /* Parse a pure-specifier. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 94a48eb..7de0bea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,13 @@ 2010-12-15 Nathan Froyd + PR c++/39859 + PR c++/44522 + PR c++/44523 + * g++.dg/parse/colon-autocorrect-1.C: New testcase. + * g++.dg/parse/colon-autocorrect-2.C: New testcase. + +2010-12-15 Nathan Froyd + PR c++/46852 * g++.dg/pr46852.C: New test. diff --git a/gcc/testsuite/g++.dg/parse/colon-autocorrect-1.C b/gcc/testsuite/g++.dg/parse/colon-autocorrect-1.C new file mode 100644 index 0000000..8e25fba --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/colon-autocorrect-1.C @@ -0,0 +1,31 @@ +// PR c++/44522 +// { dg-do compile } + +namespace x { + struct a { }; + a A0; +} + +x:a a2; // { dg-error "nested-name-specifier" } +x::a a3 = a2; + +x:a f (void) // { dg-error "nested-name-specifier" } +{ + x::a a4; // x:a would parse like a label + return a4; +} + +x::a g (x:a a4) // { dg-error "nested-name-specifier" } +{ + return a4; +} + +class B +{ + x::a f(void) // x:a would parse like a bitfield + { + x::a a4; + a4 = x:A0; // { dg-error "nested-name-specifier" } + return a4; + } +}; diff --git a/gcc/testsuite/g++.dg/parse/colon-autocorrect-2.C b/gcc/testsuite/g++.dg/parse/colon-autocorrect-2.C new file mode 100644 index 0000000..1dfcbc0 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/colon-autocorrect-2.C @@ -0,0 +1,15 @@ +// PR c++/44523 +// { dg-do compile } + +namespace x { + struct a { }; +} + +template +class foo { +}; + +foo a1; +foo a2; // { dg-error "nested-name-specifier" } + +x::a a3 = a2; // { dg-error "conversion" } -- 2.7.4