From 18759120664263a56fa993f5501cbe674383c3ef Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Mon, 21 May 2018 19:25:50 +0000 Subject: [PATCH] re PR c++/84588 (internal compiler error: Segmentation fault (contains_struct_check())) /cp 2018-05-21 Paolo Carlini PR c++/84588 * parser.c (cp_parser_maybe_commit_to_declaration, cp_parser_check_condition_declarator): New. (cp_parser_simple_declaration): Use the first above. (cp_parser_condition): Use both the above; enforce [stmt.stmt]/2 about the declarator not specifying a function or an array; improve error-recovery. /testsuite 2018-05-21 Paolo Carlini PR c++/84588 * g++.dg/cpp0x/cond1.C: New. * g++.dg/cpp1y/pr84588-1.C: Likewise. * g++.dg/cpp1y/pr84588-2.C: Likewise. * g++.dg/cpp1y/pr84588-3.C: Likewise. * g++.dg/parse/cond6.C: Likewise. * g++.dg/parse/cond7.C: Likewise. * g++.dg/parse/cond8.C: Likewise. * g++.dg/cpp1z/decomp16.C: Update. * g++.old-deja/g++.jason/cond.C: Likewise. From-SVN: r260482 --- gcc/cp/ChangeLog | 10 +++ gcc/cp/parser.c | 73 +++++++++++++++++---- gcc/testsuite/ChangeLog | 13 ++++ gcc/testsuite/g++.dg/cpp0x/cond1.C | 17 +++++ gcc/testsuite/g++.dg/cpp1y/pr84588-1.C | 25 +++++++ gcc/testsuite/g++.dg/cpp1y/pr84588-2.C | 25 +++++++ gcc/testsuite/g++.dg/cpp1y/pr84588-3.C | 25 +++++++ gcc/testsuite/g++.dg/cpp1z/decomp16.C | 2 +- gcc/testsuite/g++.dg/parse/cond6.C | 16 +++++ gcc/testsuite/g++.dg/parse/cond7.C | 12 ++++ gcc/testsuite/g++.dg/parse/cond8.C | 10 +++ gcc/testsuite/g++.old-deja/g++.jason/cond.C | 5 +- 12 files changed, 218 insertions(+), 15 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/cond1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr84588-1.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr84588-2.C create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr84588-3.C create mode 100644 gcc/testsuite/g++.dg/parse/cond6.C create mode 100644 gcc/testsuite/g++.dg/parse/cond7.C create mode 100644 gcc/testsuite/g++.dg/parse/cond8.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 29edd5f247b..db39e7b9b2a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-05-21 Paolo Carlini + + PR c++/84588 + * parser.c (cp_parser_maybe_commit_to_declaration, + cp_parser_check_condition_declarator): New. + (cp_parser_simple_declaration): Use the first above. + (cp_parser_condition): Use both the above; enforce + [stmt.stmt]/2 about the declarator not specifying + a function or an array; improve error-recovery. + 2018-05-20 Jason Merrill PR libstdc++/85843 - warning in logic_error copy constructor. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c0058085ee9..3f621911f12 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -11527,6 +11527,49 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p, } } +/* Helper function for cp_parser_condition and cp_parser_simple_declaration. + If we have seen at least one decl-specifier, and the next token + is not a parenthesis, then we must be looking at a declaration. + (After "int (" we might be looking at a functional cast.) */ + +static void +cp_parser_maybe_commit_to_declaration (cp_parser* parser, + bool any_specifiers_p) +{ + if (any_specifiers_p + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN) + && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) + && !cp_parser_error_occurred (parser)) + cp_parser_commit_to_tentative_parse (parser); +} + +/* Helper function for cp_parser_condition. Enforces [stmt.stmt]/2: + The declarator shall not specify a function or an array. Returns + TRUE if the declarator is valid, FALSE otherwise. */ + +static bool +cp_parser_check_condition_declarator (cp_parser* parser, + cp_declarator *declarator, + location_t loc) +{ + if (function_declarator_p (declarator) + || declarator->kind == cdk_array) + { + if (declarator->kind == cdk_array) + error_at (loc, "condition declares an array"); + else + error_at (loc, "condition declares a function"); + if (parser->fully_implicit_function_template_p) + abort_fully_implicit_template (parser); + cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true, + /*or_comma=*/false, + /*consume_paren=*/false); + return false; + } + else + return true; +} + /* Parse a condition. condition: @@ -11563,6 +11606,10 @@ cp_parser_condition (cp_parser* parser) &declares_class_or_enum); /* Restore the saved message. */ parser->type_definition_forbidden_message = saved_message; + + cp_parser_maybe_commit_to_declaration (parser, + type_specifiers.any_specifiers_p); + /* If all is well, we might be looking at a declaration. */ if (!cp_parser_error_occurred (parser)) { @@ -11571,6 +11618,7 @@ cp_parser_condition (cp_parser* parser) tree attributes; cp_declarator *declarator; tree initializer = NULL_TREE; + location_t loc = cp_lexer_peek_token (parser->lexer)->location; /* Parse the declarator. */ declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, @@ -11601,6 +11649,9 @@ cp_parser_condition (cp_parser* parser) bool non_constant_p; int flags = LOOKUP_ONLYCONVERTING; + if (!cp_parser_check_condition_declarator (parser, declarator, loc)) + return error_mark_node; + /* Create the declaration. */ decl = start_decl (declarator, &type_specifiers, /*initialized_p=*/true, @@ -11614,11 +11665,17 @@ cp_parser_condition (cp_parser* parser) CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1; flags = 0; } - else + else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ)) { /* Consume the `='. */ - cp_parser_require (parser, CPP_EQ, RT_EQ); - initializer = cp_parser_initializer_clause (parser, &non_constant_p); + cp_lexer_consume_token (parser->lexer); + initializer = cp_parser_initializer_clause (parser, + &non_constant_p); + } + else + { + cp_parser_error (parser, "expected initializer"); + initializer = error_mark_node; } if (BRACE_ENCLOSED_INITIALIZER_P (initializer)) maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS); @@ -12936,14 +12993,8 @@ cp_parser_simple_declaration (cp_parser* parser, goto done; } - /* If we have seen at least one decl-specifier, and the next token - is not a parenthesis, then we must be looking at a declaration. - (After "int (" we might be looking at a functional cast.) */ - if (decl_specifiers.any_specifiers_p - && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN) - && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE) - && !cp_parser_error_occurred (parser)) - cp_parser_commit_to_tentative_parse (parser); + cp_parser_maybe_commit_to_declaration (parser, + decl_specifiers.any_specifiers_p); /* Look for C++17 decomposition declaration. */ for (size_t n = 1; ; n++) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9998e63b6d8..3a669d78c2a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,16 @@ +2018-05-21 Paolo Carlini + + PR c++/84588 + * g++.dg/cpp0x/cond1.C: New. + * g++.dg/cpp1y/pr84588-1.C: Likewise. + * g++.dg/cpp1y/pr84588-2.C: Likewise. + * g++.dg/cpp1y/pr84588-3.C: Likewise. + * g++.dg/parse/cond6.C: Likewise. + * g++.dg/parse/cond7.C: Likewise. + * g++.dg/parse/cond8.C: Likewise. + * g++.dg/cpp1z/decomp16.C: Update. + * g++.old-deja/g++.jason/cond.C: Likewise. + 2018-05-21 Steven G. Kargl ChangeLog for r260480 diff --git a/gcc/testsuite/g++.dg/cpp0x/cond1.C b/gcc/testsuite/g++.dg/cpp0x/cond1.C new file mode 100644 index 00000000000..cdfdd9a27e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/cond1.C @@ -0,0 +1,17 @@ +// PR c++/84588 +// { dg-do compile { target c++11 } } + +void foo() +{ + if (int bar() {}); // { dg-error "condition declares a function" } + + for (;int bar() {};); // { dg-error "condition declares a function" } + + while (int bar() {}); // { dg-error "condition declares a function" } + + if (int a[] {}); // { dg-error "condition declares an array" } + + for (;int a[] {};); // { dg-error "condition declares an array" } + + while (int a[] {}); // { dg-error "condition declares an array" } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/pr84588-1.C b/gcc/testsuite/g++.dg/cpp1y/pr84588-1.C new file mode 100644 index 00000000000..35f3256800a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr84588-1.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++14 } } + +struct a { + void b() {} + void c(void (*) () = [] { + if (a a(int auto) {}) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct d { + void e() {} + void f(void (*) () = [] { + for (;d d(int auto) {};) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct g { + void h() {} + void i(void (*) () = [] { + while (g g(int auto) {}) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; diff --git a/gcc/testsuite/g++.dg/cpp1y/pr84588-2.C b/gcc/testsuite/g++.dg/cpp1y/pr84588-2.C new file mode 100644 index 00000000000..402ac293bcb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr84588-2.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++14 } } + +struct a { + void b() {} + void c(void (*) () = [] { + if (a a(int auto)) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct d { + void e() {} + void f(void (*) () = [] { + for (;d d(int auto);) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct g { + void h() {} + void i(void (*) () = [] { + while (g g(int auto)) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; diff --git a/gcc/testsuite/g++.dg/cpp1y/pr84588-3.C b/gcc/testsuite/g++.dg/cpp1y/pr84588-3.C new file mode 100644 index 00000000000..477c3e3f51c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr84588-3.C @@ -0,0 +1,25 @@ +// { dg-do compile { target c++14 } } + +struct a { + void b() {} + void c(void (*) () = [] { + if (a a(int auto)JUNK) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct d { + void e() {} + void f(void (*) () = [] { + for (;d d(int auto)JUNK;) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; + +struct g { + void h() {} + void i(void (*) () = [] { + while (g g(int auto)JUNK) // { dg-error "two or more data types|condition declares a function" } + ; + }) {} +}; diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp16.C b/gcc/testsuite/g++.dg/cpp1z/decomp16.C index 7589c8015a5..dad69b89c08 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp16.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp16.C @@ -8,7 +8,7 @@ void foo () { auto [ a, b ] = A (); - for (; auto [ a, b ] = A (); ) // { dg-error "expected" } + for (; auto [ a, b ] = A (); ) // { dg-error "expected|no match" } ; for (; false; auto [ a, b ] = A ()) // { dg-error "expected" } ; diff --git a/gcc/testsuite/g++.dg/parse/cond6.C b/gcc/testsuite/g++.dg/parse/cond6.C new file mode 100644 index 00000000000..78d033727a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/cond6.C @@ -0,0 +1,16 @@ +// PR c++/84588 + +void foo() +{ + if (int bar()); // { dg-error "condition declares a function" } + + for (;int bar();); // { dg-error "condition declares a function" } + + while (int bar()); // { dg-error "condition declares a function" } + + if (int a[]); // { dg-error "condition declares an array" } + + for (;int a[];); // { dg-error "condition declares an array" } + + while (int a[]); // { dg-error "condition declares an array" } +} diff --git a/gcc/testsuite/g++.dg/parse/cond7.C b/gcc/testsuite/g++.dg/parse/cond7.C new file mode 100644 index 00000000000..45befe62326 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/cond7.C @@ -0,0 +1,12 @@ +// PR c++/84588 + +bool (foo()) { return 0; } // declaration + +void bar() +{ + if (bool (foo())); // expression + + for (;bool (foo());); // expression + + while (bool (foo())); // expression +} diff --git a/gcc/testsuite/g++.dg/parse/cond8.C b/gcc/testsuite/g++.dg/parse/cond8.C new file mode 100644 index 00000000000..40ba29d6439 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/cond8.C @@ -0,0 +1,10 @@ +// PR c++/84588 + +void foo() +{ + if (int x); // { dg-error "expected initializer" } + + for (;int x;); // { dg-error "expected initializer" } + + while (int x); // { dg-error "expected initializer" } +} diff --git a/gcc/testsuite/g++.old-deja/g++.jason/cond.C b/gcc/testsuite/g++.old-deja/g++.jason/cond.C index dfc21dd5378..f9287090fb2 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/cond.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/cond.C @@ -47,11 +47,10 @@ int main() if (struct B * foo = new B) ; - if (int f () = 1) // { dg-warning "extern" "extern" } - // { dg-error "is initialized like a variable" "var" { target *-*-* } .-1 } + if (int f () = 1) // { dg-error "declares a function" } ; - if (int a[2] = {1, 2}) // { dg-error "extended init" "" { target { ! c++11 } } } + if (int a[2] = {1, 2}) // { dg-error "declares an array" } ; } -- 2.30.2