PR c++/91338 - Implement P1161R3: Deprecate a[b,c].
authorMarek Polacek <polacek@redhat.com>
Mon, 5 Aug 2019 19:01:15 +0000 (19:01 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 5 Aug 2019 19:01:15 +0000 (19:01 +0000)
* 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

12 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-opts.c
gcc/c-family/c.opt
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/comma1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/comma2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/comma3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/comma4.C [new file with mode: 0644]

index 959d15b5041698b63fd2f1d5807e60ec3a761b26..99c3669eeffdd7bcf8e68b4b96d22c78845efa45 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-05  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/91338 - Implement P1161R3: Deprecate a[b,c].
+       * doc/invoke.texi: Document -Wcomma-subscript.
+
 2019-08-05  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-core.h (tree_function_decl): Make function_code an
index e6452542bcc961374b901248494e094033216a9c..693a546347c0ea33be27fe57ce4e12c4580d0948 100644 (file)
@@ -1,3 +1,10 @@
+2019-08-05  Marek Polacek  <polacek@redhat.com>
+
+       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  <jakub@redhat.com>
 
        * c-pragma.h (enum pragma_kind): Add PRAGMA_OMP_LOOP.
index e97bbdf5c6f0e6c9664259c607dd99f664d72556..2d4af63cde4a3213e77588ff93fcdc12e37fdb29 100644 (file)
@@ -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;
index 4c8b00260008d26873b3fbb174b437a2ffb03875..257cadfa5f1d77d194967e48bf54efdd7e1f339e 100644 (file)
@@ -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.
index 2b281c1672caefcdab857e32435aa68e5efa1ad7..3e4900c34fecb655d8554acd961c3af952e20990 100644 (file)
@@ -1,3 +1,12 @@
+2019-08-05  Marek Polacek  <polacek@redhat.com>
+
+       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  <jason@redhat.com>
 
        * semantics.c (force_paren_expr): Preserve location.
index ebeffdb775fe78719603508f86bb5d8c640a820e..1a5ae147b84535c8468cccb38bf589486e1fc03e 100644 (file)
@@ -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
index 7b3c77b8033a53e7a53e6f3ec9a0863a2041c743..01aab60f8954df37e8d0ac18357126a8c4f085cb 100644 (file)
@@ -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
index 2db452910db7ad29dbfbb8a86189400d5eb47be1..0e8e141bba6afd1087ffceb65f7fe0e89f815eef 100644 (file)
@@ -1,3 +1,11 @@
+2019-08-05  Marek Polacek  <polacek@redhat.com>
+
+       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  <richard.sandiford@arm.com>
 
        * 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 (file)
index 0000000..8ffe5d7
--- /dev/null
@@ -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 (file)
index 0000000..15fd26a
--- /dev/null
@@ -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 (file)
index 0000000..c39dd4b
--- /dev/null
@@ -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 (file)
index 0000000..23183ad
--- /dev/null
@@ -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{})];
+}