From ab574db6b9b2c06b9d68326a9cab6b4193a303e1 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 5 Aug 2019 19:01:15 +0000 Subject: [PATCH] PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. * c-opts.c (c_common_post_options): Enable -Wcomma-subscript by default for C++2a, unless -Wno-deprecated. * c.opt (Wcomma-subscript): New warning. * parser.c (cp_parser_postfix_open_square_expression): Warn about uses of a comma operator within a subscripting expression. (cp_parser_skip_to_closing_square_bracket_1): New function, made out of... (cp_parser_skip_to_closing_square_bracket): ...this. * doc/invoke.texi: Document -Wcomma-subscript. * g++.dg/cpp2a/comma1.C: New test. * g++.dg/cpp2a/comma2.C: New test. * g++.dg/cpp2a/comma3.C: New test. * g++.dg/cpp2a/comma4.C: New test. From-SVN: r274121 --- gcc/ChangeLog | 5 ++ gcc/c-family/ChangeLog | 7 +++ gcc/c-family/c-opts.c | 4 ++ gcc/c-family/c.opt | 4 ++ gcc/cp/ChangeLog | 9 ++++ gcc/cp/parser.c | 80 ++++++++++++++++++++++++++--- gcc/doc/invoke.texi | 21 +++++++- gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/g++.dg/cpp2a/comma1.C | 26 ++++++++++ gcc/testsuite/g++.dg/cpp2a/comma2.C | 27 ++++++++++ gcc/testsuite/g++.dg/cpp2a/comma3.C | 27 ++++++++++ gcc/testsuite/g++.dg/cpp2a/comma4.C | 27 ++++++++++ 12 files changed, 236 insertions(+), 9 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/comma1.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/comma2.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/comma3.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/comma4.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 959d15b5041..99c3669eeff 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2019-08-05 Marek Polacek + + PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. + * doc/invoke.texi: Document -Wcomma-subscript. + 2019-08-05 Richard Sandiford * tree-core.h (tree_function_decl): Make function_code an diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index e6452542bcc..693a546347c 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2019-08-05 Marek Polacek + + PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. + * c-opts.c (c_common_post_options): Enable -Wcomma-subscript by + default for C++2a, unless -Wno-deprecated. + * c.opt (Wcomma-subscript): New warning. + 2019-07-20 Jakub Jelinek * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_LOOP. diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c index e97bbdf5c6f..2d4af63cde4 100644 --- a/gcc/c-family/c-opts.c +++ b/gcc/c-family/c-opts.c @@ -916,6 +916,10 @@ c_common_post_options (const char **pfilename) if (!global_options_set.x_warn_register) warn_register = cxx_dialect >= cxx17; + /* -Wcomma-subscript is enabled by default in C++20. */ + if (!global_options_set.x_warn_comma_subscript) + warn_comma_subscript = (cxx_dialect >= cxx2a && warn_deprecated); + /* Declone C++ 'structors if -Os. */ if (flag_declone_ctor_dtor == -1) flag_declone_ctor_dtor = optimize_size; diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 4c8b0026000..257cadfa5f1 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -428,6 +428,10 @@ Wclobbered C ObjC C++ ObjC++ Var(warn_clobbered) Warning EnabledBy(Wextra) Warn about variables that might be changed by \"longjmp\" or \"vfork\". +Wcomma-subscript +C++ ObjC++ Var(warn_comma_subscript) Warning +Warn about uses of a comma operator within a subscripting expression. + Wcomment C ObjC C++ ObjC++ CPP(warn_comments) CppReason(CPP_W_COMMENTS) Var(cpp_warn_comment) Init(0) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall) Warn about possibly nested block comments, and C++ comments spanning more than one physical line. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2b281c1672c..3e4900c34fe 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2019-08-05 Marek Polacek + + PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. + * parser.c (cp_parser_postfix_open_square_expression): Warn about uses + of a comma operator within a subscripting expression. + (cp_parser_skip_to_closing_square_bracket_1): New function, made out + of... + (cp_parser_skip_to_closing_square_bracket): ...this. + 2019-08-05 Jason Merrill * semantics.c (force_paren_expr): Preserve location. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index ebeffdb775f..1a5ae147b84 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2669,6 +2669,8 @@ static bool cp_parser_init_statement_p (cp_parser *); static bool cp_parser_skip_to_closing_square_bracket (cp_parser *); +static int cp_parser_skip_to_closing_square_bracket_1 + (cp_parser *, enum cpp_ttype); /* Concept-related syntactic transformations */ @@ -7522,7 +7524,33 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, index = cp_parser_braced_list (parser, &expr_nonconst_p); } else - index = cp_parser_expression (parser); + { + /* [depr.comma.subscript]: A comma expression appearing as + the expr-or-braced-init-list of a subscripting expression + is deprecated. A parenthesized comma expression is not + deprecated. */ + if (warn_comma_subscript) + { + /* Save tokens so that we can put them back. */ + cp_lexer_save_tokens (parser->lexer); + + /* Look for ',' that is not nested in () or {}. */ + if (cp_parser_skip_to_closing_square_bracket_1 (parser, + CPP_COMMA) == -1) + { + auto_diagnostic_group d; + warning_at (cp_lexer_peek_token (parser->lexer)->location, + OPT_Wcomma_subscript, + "top-level comma expression in array subscript " + "is deprecated"); + } + + /* Roll back the tokens we skipped. */ + cp_lexer_rollback_tokens (parser->lexer); + } + + index = cp_parser_expression (parser); + } } parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; @@ -22857,16 +22885,25 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p) } /* Consume tokens up to, and including, the next non-nested closing `]'. - Returns true iff we found a closing `]'. */ + Returns 1 iff we found a closing `]'. Returns -1 if OR_TTYPE is not + CPP_EOF and we found an unnested token of that type. */ -static bool -cp_parser_skip_to_closing_square_bracket (cp_parser *parser) +static int +cp_parser_skip_to_closing_square_bracket_1 (cp_parser *parser, + enum cpp_ttype or_ttype) { unsigned square_depth = 0; + unsigned paren_depth = 0; + unsigned brace_depth = 0; while (true) { - cp_token * token = cp_lexer_peek_token (parser->lexer); + cp_token *token = cp_lexer_peek_token (parser->lexer); + + /* Have we found what we're looking for before the closing square? */ + if (token->type == or_ttype && or_ttype != CPP_EOF + && brace_depth == 0 && paren_depth == 0 && square_depth == 0) + return -1; switch (token->type) { @@ -22876,20 +22913,38 @@ cp_parser_skip_to_closing_square_bracket (cp_parser *parser) /* FALLTHRU */ case CPP_EOF: /* If we've run out of tokens, then there is no closing `]'. */ - return false; + return 0; case CPP_OPEN_SQUARE: ++square_depth; break; case CPP_CLOSE_SQUARE: - if (!square_depth--) + if (square_depth-- == 0) { cp_lexer_consume_token (parser->lexer); - return true; + return 1; } break; + case CPP_OPEN_BRACE: + ++brace_depth; + break; + + case CPP_CLOSE_BRACE: + if (brace_depth-- == 0) + return 0; + break; + + case CPP_OPEN_PAREN: + ++paren_depth; + break; + + case CPP_CLOSE_PAREN: + if (paren_depth-- == 0) + return 0; + break; + default: break; } @@ -22899,6 +22954,15 @@ cp_parser_skip_to_closing_square_bracket (cp_parser *parser) } } +/* Consume tokens up to, and including, the next non-nested closing `]'. + Returns true iff we found a closing `]'. */ + +static bool +cp_parser_skip_to_closing_square_bracket (cp_parser *parser) +{ + return cp_parser_skip_to_closing_square_bracket_1 (parser, CPP_EOF) == 1; +} + /* Return true if we are looking at an array-designator, false otherwise. */ static bool diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7b3c77b8033..01aab60f895 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -230,7 +230,8 @@ in the following sections. -fvisibility-inlines-hidden @gol -fvisibility-ms-compat @gol -fext-numeric-literals @gol --Wabi=@var{n} -Wabi-tag -Wconversion-null -Wctor-dtor-privacy @gol +-Wabi=@var{n} -Wabi-tag -Wcomma-subscript -Wconversion-null @gol +-Wctor-dtor-privacy @gol -Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol -Wliteral-suffix @gol -Wmultiple-inheritance -Wno-init-list-lifetime @gol @@ -3037,6 +3038,24 @@ Warn when a type with an ABI tag is used in a context that does not have that ABI tag. See @ref{C++ Attributes} for more information about ABI tags. +@item -Wcomma-subscript @r{(C++ and Objective-C++ only)} +@opindex Wcomma-subscript +@opindex Wno-comma-subscript +Warn about uses of a comma expression within a subscripting expression. +This usage was deprecated in C++2a. However, a comma expression wrapped +in @code{( )} is not deprecated. Example: + +@smallexample +@group +void f(int *a, int b, int c) @{ + a[b,c]; // deprecated + a[(b,c)]; // OK +@} +@end group +@end smallexample + +Enabled by default with @option{-std=c++2a}. + @item -Wctor-dtor-privacy @r{(C++ and Objective-C++ only)} @opindex Wctor-dtor-privacy @opindex Wno-ctor-dtor-privacy diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2db452910db..0e8e141bba6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-08-05 Marek Polacek + + PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. + * g++.dg/cpp2a/comma1.C: New test. + * g++.dg/cpp2a/comma2.C: New test. + * g++.dg/cpp2a/comma3.C: New test. + * g++.dg/cpp2a/comma4.C: New test. + 2019-08-05 Richard Sandiford * gcc.target/aarch64/sve/mask_load_1.c: New test. diff --git a/gcc/testsuite/g++.dg/cpp2a/comma1.C b/gcc/testsuite/g++.dg/cpp2a/comma1.C new file mode 100644 index 00000000000..8ffe5d74e61 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/comma1.C @@ -0,0 +1,26 @@ +// PR c++/91338 - P1161R3: Deprecate a[b,c]. +// { dg-do compile { target c++11 } } + +struct S { + int operator,(int) { return 42; } +}; + +void +fn (int *a, int b, int c) +{ + a[b,c]; // { dg-warning "top-level comma expression in array subscript is deprecated" "" { target c++2a } } + a[(b,c)]; + + a[(void) b, c]; // { dg-warning "top-level comma expression in array subscript is deprecated" "" { target c++2a } } + a[((void) b, c)]; + + a[(void) b, (void) c, (void) b, b]; // { dg-warning "top-level comma expression in array subscript is deprecated" "" { target c++2a } } + a[((void) b, (void) c, (void) b, b)]; + + a[S(), 10]; // { dg-warning "top-level comma expression in array subscript is deprecated" "" { target c++2a } } + a[(S(), 10)]; + + a[int{(1,2)}]; + a[int{(1,2)}, int{}]; // { dg-warning "top-level comma expression in array subscript is deprecated" "" { target c++2a } } + a[(int{(1,2)}, int{})]; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/comma2.C b/gcc/testsuite/g++.dg/cpp2a/comma2.C new file mode 100644 index 00000000000..15fd26ab400 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/comma2.C @@ -0,0 +1,27 @@ +// PR c++/91338 - P1161R3: Deprecate a[b,c]. +// { dg-do compile { target c++2a } } +// { dg-options "-Wno-comma-subscript" } + +struct S { + int operator,(int) { return 42; } +}; + +void +fn (int *a, int b, int c) +{ + a[b,c]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(b,c)]; + + a[(void) b, c]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[((void) b, c)]; + + a[(void) b, (void) c, (void) b, b]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[((void) b, (void) c, (void) b, b)]; + + a[S(), 10]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(S(), 10)]; + + a[int{(1,2)}]; + a[int{(1,2)}, int{}]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(int{(1,2)}, int{})]; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/comma3.C b/gcc/testsuite/g++.dg/cpp2a/comma3.C new file mode 100644 index 00000000000..c39dd4b483a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/comma3.C @@ -0,0 +1,27 @@ +// PR c++/91338 - P1161R3: Deprecate a[b,c]. +// { dg-do compile { target c++11 } } +// { dg-options "-Wcomma-subscript" } + +struct S { + int operator,(int) { return 42; } +}; + +void +fn (int *a, int b, int c) +{ + a[b,c]; // { dg-warning "top-level comma expression in array subscript is deprecated" } + a[(b,c)]; + + a[(void) b, c]; // { dg-warning "top-level comma expression in array subscript is deprecated" } + a[((void) b, c)]; + + a[(void) b, (void) c, (void) b, b]; // { dg-warning "top-level comma expression in array subscript is deprecated" } + a[((void) b, (void) c, (void) b, b)]; + + a[S(), 10]; // { dg-warning "top-level comma expression in array subscript is deprecated" } + a[(S(), 10)]; + + a[int{(1,2)}]; + a[int{(1,2)}, int{}]; // { dg-warning "top-level comma expression in array subscript is deprecated" } + a[(int{(1,2)}, int{})]; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/comma4.C b/gcc/testsuite/g++.dg/cpp2a/comma4.C new file mode 100644 index 00000000000..23183ad7bc2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/comma4.C @@ -0,0 +1,27 @@ +// PR c++/91338 - P1161R3: Deprecate a[b,c]. +// { dg-do compile { target c++2a } } +// { dg-options "-Wno-deprecated" } + +struct S { + int operator,(int) { return 42; } +}; + +void +fn (int *a, int b, int c) +{ + a[b,c]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(b,c)]; + + a[(void) b, c]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[((void) b, c)]; + + a[(void) b, (void) c, (void) b, b]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[((void) b, (void) c, (void) b, b)]; + + a[S(), 10]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(S(), 10)]; + + a[int{(1,2)}]; + a[int{(1,2)}, int{}]; // { dg-bogus "top-level comma expression in array subscript is deprecated" } + a[(int{(1,2)}, int{})]; +}