]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Implement C++26 P3176R1 - The Oxford variadic comma
authorJakub Jelinek <jakub@redhat.com>
Sat, 30 Nov 2024 00:49:21 +0000 (01:49 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sat, 30 Nov 2024 00:49:21 +0000 (01:49 +0100)
While we are already in stage3, I wonder if implementing this small paper
wouldn't be useful even for GCC 15, so that we have in the GCC world one
extra year of deprecation of variadic ellipsis without preceding comma.

The paper just deprecates something, I'd hope most of the C++ code in the
wild when it uses variadic functions at all uses the comma before the
ellipsis.

2024-11-30  Jakub Jelinek  <jakub@redhat.com>

gcc/c-family/
* c.opt (Wdeprecated-variadic-comma-omission): New option.
* c.opt.urls: Regenerate.
* c-opts.cc (c_common_post_options): Default to
-Wdeprecated-variadic-comma-omission for C++26 or -Wpedantic.
gcc/cp/
* parser.cc: Implement C++26 P3176R1 - The Oxford variadic comma.
(cp_parser_parameter_declaration_clause): Emit
-Wdeprecated-variadic-comma-omission warnings.
gcc/
* doc/invoke.texi (-Wdeprecated-variadic-comma-omission): Document.
gcc/testsuite/
* g++.dg/cpp26/variadic-comma1.C: New test.
* g++.dg/cpp26/variadic-comma2.C: New test.
* g++.dg/cpp26/variadic-comma3.C: New test.
* g++.dg/cpp26/variadic-comma4.C: New test.
* g++.dg/cpp26/variadic-comma5.C: New test.
* g++.dg/cpp1z/fold10.C: Expect a warning for C++26.
* g++.dg/ext/attrib33.C: Likewise.
* g++.dg/cpp1y/lambda-generic-variadic19.C: Likewise.
* g++.dg/cpp2a/lambda-generic10.C: Likewise.
* g++.dg/cpp0x/lambda/lambda-const3.C: Likewise.
* g++.dg/cpp0x/variadic164.C: Likewise.
* g++.dg/cpp0x/variadic17.C: Likewise.
* g++.dg/cpp0x/udlit-args-neg.C: Likewise.
* g++.dg/cpp0x/variadic28.C: Likewise.
* g++.dg/cpp0x/gen-attrs-33.C: Likewise.
* g++.dg/cpp23/explicit-obj-diagnostics3.C: Likewise.
* g++.old-deja/g++.law/operators15.C: Likewise.
* g++.old-deja/g++.mike/p811.C: Likewise.
* g++.old-deja/g++.mike/p12306.C (printf): Add , before ... .
* g++.dg/analyzer/fd-bind-pr107783.C (bind): Likewise.
* g++.dg/cpp0x/vt-65790.C (printf): Likewise.
libstdc++-v3/
* include/std/functional (_Bind_check_arity): Add , before ... .
* include/bits/refwrap.h (_Mem_fn_traits, _Weak_result_type_impl):
Likewise.
* include/tr1/type_traits (is_function): Likewise.

29 files changed:
gcc/c-family/c-opts.cc
gcc/c-family/c.opt
gcc/c-family/c.opt.urls
gcc/cp/parser.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/analyzer/fd-bind-pr107783.C
gcc/testsuite/g++.dg/cpp0x/gen-attrs-33.C
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C
gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C
gcc/testsuite/g++.dg/cpp0x/variadic164.C
gcc/testsuite/g++.dg/cpp0x/variadic17.C
gcc/testsuite/g++.dg/cpp0x/variadic28.C
gcc/testsuite/g++.dg/cpp0x/vt-65790.C
gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic19.C
gcc/testsuite/g++.dg/cpp1z/fold10.C
gcc/testsuite/g++.dg/cpp23/explicit-obj-diagnostics3.C
gcc/testsuite/g++.dg/cpp26/variadic-comma1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp26/variadic-comma2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp26/variadic-comma3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp26/variadic-comma4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp26/variadic-comma5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/lambda-generic10.C
gcc/testsuite/g++.dg/ext/attrib33.C
gcc/testsuite/g++.old-deja/g++.law/operators15.C
gcc/testsuite/g++.old-deja/g++.mike/p12306.C
gcc/testsuite/g++.old-deja/g++.mike/p811.C
libstdc++-v3/include/bits/refwrap.h
libstdc++-v3/include/std/functional
libstdc++-v3/include/tr1/type_traits

index 0871eb30372640cd5905115733d6b361be9a3e37..7d139a7adf314ebd31c234052609834a58da9499 100644 (file)
@@ -1061,6 +1061,11 @@ c_common_post_options (const char **pfilename)
                       warn_array_compare,
                       warn_array_compare || deprecated_in (cxx20));
 
+  /* -Wdeprecated-variadic-comma-omission is enabled by default in C++26.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                      warn_deprecated_variadic_comma_omission,
+                      deprecated_in (cxx26));
+
   /* -Wtemplate-id-cdtor is enabled by default in C++20.  */
   SET_OPTION_IF_UNSET (&global_options, &global_options_set,
                       warn_template_id_cdtor,
index 467d361bb3a7606ef2ef5e210bf72a0a89a25b93..0d255561b1bdcdf654b1310f97d9d059b3b3b284 100644 (file)
@@ -672,6 +672,10 @@ Wdeprecated-non-prototype
 C ObjC Var(warn_deprecated_non_prototype) Init(-1) Warning
 Warn about calls with arguments to functions declared without parameters.
 
+Wdeprecated-variadic-comma-omission
+C++ ObjC++ Var(warn_deprecated_variadic_comma_omission) Warning
+Warn about deprecated omission of comma before ... in varargs function declaration.
+
 Wdesignated-init
 C ObjC Var(warn_designated_init) Init(1) Warning
 Warn about positional initialization of structs requiring designated initializers.
index 56c814e1b5cadf9246c28c471b33ae3412eabc6d..8fbe3bd26989a88223a5869e937e9308e954fcc5 100644 (file)
@@ -310,6 +310,9 @@ UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-literal-operato
 Wdeprecated-non-prototype
 UrlSuffix(gcc/Warning-Options.html#index-Wdeprecated-non-prototype)
 
+Wdeprecated-variadic-comma-omission
+UrlSuffix(gcc/C_002b_002b-Dialect-Options.html#index-Wdeprecated-variadic-comma-omission)
+
 Wdesignated-init
 UrlSuffix(gcc/Warning-Options.html#index-Wdesignated-init)
 
index f519ab014640ea9e946aae97355245995f78fcd1..94069d7a1fe9832aa80e638e89a3c464df3ac60a 100644 (file)
@@ -25770,6 +25770,16 @@ cp_parser_parameter_declaration_clause (cp_parser* parser,
      omitted.  */
   else if (token->type == CPP_ELLIPSIS)
     {
+      /* Deprecated by P3176R1 in C++26.  */
+      if (warn_deprecated_variadic_comma_omission)
+       {
+         gcc_rich_location richloc (token->location);
+         richloc.add_fixit_insert_before (", ");
+         warning_at (&richloc, OPT_Wdeprecated_variadic_comma_omission,
+                     "omission of %<,%> before varargs %<...%> is "
+                     "deprecated in C++26");
+       }
+
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* And remember that we saw it.  */
index 18a5754a0973c3930792d8fa9e189596d2f7725e..fa2532f437b6ab8576e0b4120a64b4f2c647fe76 100644 (file)
@@ -4069,6 +4069,22 @@ string operator "" _i18n(const char*, std::size_t); // deprecated
 string operator ""_i18n(const char*, std::size_t); // preferred
 @end smallexample
 
+@opindex Wdeprecated-variadic-comma-omission
+@opindex Wno-deprecated-variadic-comma-omission
+@item -Wdeprecated-variadic-comma-omission @r{(C++ and Objective-C++ only)}
+Warn that omitting a comma before the varargs @code{...} at the end of
+a function parameter list is deprecated.  This warning is enabled by
+default in C++26, or with explicit @option{-Wdeprecated}.
+
+@smallexample
+void f1(int...); // deprecated
+void f1(int, ...); // preferred
+template <typename ...T>
+void f2(T...); // ok
+template <typename ...T>
+void f3(T......); // deprecated
+@end smallexample
+
 @opindex Welaborated-enum-base
 @opindex Wno-elaborated-enum-base
 @item -Wno-elaborated-enum-base
@@ -10348,8 +10364,9 @@ In C++, explicitly specifying @option{-Wdeprecated} also enables
 warnings about some features that are deprecated in later language
 standards, specifically @option{-Wcomma-subscript},
 @option{-Wvolatile}, @option{-Wdeprecated-enum-float-conversion},
-@option{-Wdeprecated-enum-enum-conversion}, and
-@option{-Wdeprecated-literal-operator}.
+@option{-Wdeprecated-enum-enum-conversion},
+@option{-Wdeprecated-literal-operator}, and
+@option{-Wdeprecated-variadic-comma-omission}.
 
 @opindex Wno-deprecated-declarations
 @opindex Wdeprecated-declarations
index eb5e23c82cf1fcc154634359d886a459bb1500ce..318e1486e8e2dba9a7e190fc0b9f8bc616ae3e82 100644 (file)
@@ -7,5 +7,5 @@ struct _Bind {
   _Bind(_Bind &);
 };
 template <typename _Func, typename _BoundArgs>
-_Bind bind(_Func, _BoundArgs &&...);
+_Bind bind(_Func, _BoundArgs &&...);
 void test01() { bind(minus(), _2, _1); }
index efb2a1ad6d068e3946d519b4e59565cb18f1eab7..485d349ecfcee6d01b362b3d5465bbab839de54a 100644 (file)
@@ -5,7 +5,7 @@
 template <int N>
 struct T
 {
-  void foo [[gnu::format (printf,2,3)]] (char const * ...);
+  void foo [[gnu::format (printf,2,3)]] (char const * ...);    // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 };
 
 template struct T<3>;
index a1ffaddc4a7aac8a16b1c345c9473eddd99a510a..1767dd7117082629b95a1b658c1cd82ece2c49e9 100644 (file)
@@ -7,7 +7,7 @@ struct FF
 {
   template < class F, class ... Ts >
   void
-  operator () (F & ...)
+  operator () (F & ...)                        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
   {
     const int n = sizeof ... (Ts) + 1;
     void *mutexes[n];
index 72cb4b4c4cbad466730f9f49a9a06e2c13da24f6..27508882f8597fe1066d55801e014a17fd679ec1 100644 (file)
@@ -27,6 +27,7 @@ operator ""_Foo(const char16_t *);    // { dg-error "1:.Foo operator\"\"_Foo\\(cons
 
 Foo
 operator ""_Foo(char...);      // { dg-error "1:.Foo operator\"\"_Foo\\(char, \\.\\.\\.\\). has invalid argument list" }
+                               // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } .-1 }
 
 Foo
 operator ""_Foo(unsigned long long int, char); // { dg-error "1:.Foo operator\"\"_Foo\\(long long unsigned int, char\\). has invalid argument list" }
index 8f9cdb18c2d8c5263ef5d7311a1af5fbee3ada31..a3855346f5cc8e72d3faf8a4cc893fb32faf5198 100644 (file)
@@ -8,5 +8,5 @@ template <typename Tuple, typename... Tuples, int... ElementIndices,
           typename =
               typename tuple<slice_result<ElementIndices, Tuples...>,
                              slice_result<ElementIndices, Tuples...>...>::type> // { dg-error "parameter pack" }
-void zip_with(Tuple...);
+void zip_with(Tuple...);       // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 decltype(zip_with(0)) d;       // { dg-error "no match" }
index d54022a7c7b2b2de21b27a531ca010852bf52833..4791bb4e0fc0765b951bfe2084689c2ce29c82ed 100644 (file)
@@ -2,7 +2,7 @@
 template<typename R, typename... ArgTypes>
 struct make_function_type
 {
-  typedef R type(const ArgTypes&......);
+  typedef R type(const ArgTypes&......);               // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 };
 
 template<typename T, typename U>
@@ -16,6 +16,6 @@ struct is_same<T, T> {
 };
 
 int a0[is_same<make_function_type<int>::type, int(...)>::value? 1 : -1];
-int a1[is_same<make_function_type<int, float>::type, int(const float&...)>::value? 1 : -1];
+int a1[is_same<make_function_type<int, float>::type, int(const float&...)>::value? 1 : -1];            // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 int a2[is_same<make_function_type<int, float>::type, int(const float&,...)>::value? 1 : -1];
-int a3[is_same<make_function_type<int, float, double>::type, int(const float&, double const&...)>::value? 1 : -1];
+int a3[is_same<make_function_type<int, float, double>::type, int(const float&, double const&...)>::value? 1 : -1];             // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
index b0278613cbff9b5d5daa21a21a86a63d1ea91ec1..57f6d23b21e7a24626194edb1e8b94b8a3ed512b 100644 (file)
@@ -3,7 +3,7 @@ template<typename Signature>
 struct function_traits;
 
 template<typename R, typename... ArgTypes>
-struct function_traits<R(ArgTypes......)> {
+struct function_traits<R(ArgTypes......)> {    // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
   typedef R result_type;
 };
 
@@ -17,9 +17,9 @@ struct same_type<T, T> {
   static const bool value = true;
 };
 
-int a0[same_type<function_traits<int(double, char...)>::result_type, int>::value? 1 : -1];
+int a0[same_type<function_traits<int(double, char...)>::result_type, int>::value? 1 : -1];     // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 int a1[same_type<function_traits<int(double, char,...)>::result_type, int>::value? 1 : -1];
 int a2[same_type<function_traits<int(char,...)>::result_type, int>::value? 1 : -1];
 int a3[same_type<function_traits<int(...)>::result_type, int>::value? 1 : -1];
-int a4[same_type<function_traits<int(double x, char...)>::result_type, int>::value? 1 : -1];
-int a5[same_type<function_traits<int(double, char y...)>::result_type, int>::value? 1 : -1];
+int a4[same_type<function_traits<int(double x, char...)>::result_type, int>::value? 1 : -1];   // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
+int a5[same_type<function_traits<int(double, char y...)>::result_type, int>::value? 1 : -1];   // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
index 477e9884304df1b64988d110a22dc3b2b5bb9dcd..4e899630d63b498cc4eefade5d49e8445cb2303e 100644 (file)
@@ -1,7 +1,7 @@
 // PR c++/65790
 // { dg-do compile { target c++11 } }
 
-extern "C" int printf(const char* ...);
+extern "C" int printf(const char*, ...);
 
 namespace std
 {
index e78677de0b523b619d6398a839cfbdeb7a9a897e..0fb873dd4f252c38a44fb44e295c3403378a8539 100644 (file)
@@ -1,4 +1,4 @@
 // PR c++/86728
 // { dg-do compile { target c++14 } }
 
-auto c = [](auto x ...) { };
+auto c = [](auto x ...) { };   // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
index 1bd39a05400015b77126dd91b8cfe8cc301ed0bc..87aee5b50f2fdabd808c0172d2eb136f36c0c129 100644 (file)
@@ -4,7 +4,7 @@
 template <int...> struct seq {};
 template <bool> struct S {
     template <typename Args>
-    constexpr static void call(Args&&...) {}
+    constexpr static void call(Args&&...) {}   // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 };
 
 template <int ...Idx,typename ...Args>
index f6a892eb06919c2b23610bafce0c6257d3eea820..4ff13af2923903958abb5d3c0c987dd25cb2326d 100644 (file)
@@ -24,7 +24,7 @@ void S::f12(this S s = {}) {} // { dg-error "an explicit object parameter may no
 
 struct S0 {
   template<typename Selves>
-  void f(this Selves...) {}
+  void f(this Selves...) {}        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void g(this Selves... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -37,7 +37,7 @@ struct S0 {
   void k(this Selves...) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
 
   template<typename Selves>
-  void fd(this Selves...);
+  void fd(this Selves...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void gd(this Selves... selves);  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -52,7 +52,7 @@ struct S0 {
 
 struct S1 {
   template<typename Selves>
-  void f(this Selves&...) {}
+  void f(this Selves&...) {}        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void g(this Selves&... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -65,7 +65,7 @@ struct S1 {
   void k(this Selves&...) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
 
   template<typename Selves>
-  void fd(this Selves&...);
+  void fd(this Selves&...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void gd(this Selves&... selves);  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -80,7 +80,7 @@ struct S1 {
 
 struct S2 {
   template<typename Selves>
-  void f(this Selves&&...) {}
+  void f(this Selves&&...) {}        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void g(this Selves&&... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -93,7 +93,7 @@ struct S2 {
   void k(this Selves&&...) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
 
   template<typename Selves>
-  void fd(this Selves&&...);
+  void fd(this Selves&&...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void gd(this Selves&&... selves);  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -108,7 +108,7 @@ struct S2 {
 
 struct S3 {
   template<typename Selves>
-  void f(this Selves const&...) {}
+  void f(this Selves const&...) {}        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void g(this Selves const&... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -121,7 +121,7 @@ struct S3 {
   void k(this Selves const&...) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
 
   template<typename Selves>
-  void fd(this Selves const&...);
+  void fd(this Selves const&...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void gd(this Selves const&... selves);  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -136,7 +136,7 @@ struct S3 {
 
 struct S4 {
   template<typename Selves>
-  void f(this Selves const&&...) {}
+  void f(this Selves const&&...) {}        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void g(this Selves const&&... selves) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
@@ -149,7 +149,7 @@ struct S4 {
   void k(this Selves const&&...) {}  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
 
   template<typename Selves>
-  void fd(this Selves const&&...);
+  void fd(this Selves const&&...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
   template<typename Selves>
   void gd(this Selves const&&... selves);  // { dg-error "an explicit object parameter cannot be a function parameter pack" }
diff --git a/gcc/testsuite/g++.dg/cpp26/variadic-comma1.C b/gcc/testsuite/g++.dg/cpp26/variadic-comma1.C
new file mode 100644 (file)
index 0000000..d5cf13f
--- /dev/null
@@ -0,0 +1,18 @@
+// P3176R1 - The Oxford variadic comma
+// { dg-do compile { target c++11 } }
+
+void f1 (int...);              // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++26 } }
+#if __cplusplus >= 202002L
+void f2 (auto...);
+void f3 (auto......);          // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++26 } }
+#endif
+template <typename ...T>
+void f4 (T......);             // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++26 } }
+template <typename ...T>
+void f5 (T...);
+template <typename ...T>
+void f6 (T..., int...);                // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++26 } }
+void
+f7 (char...)                   // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++26 } }
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/variadic-comma2.C b/gcc/testsuite/g++.dg/cpp26/variadic-comma2.C
new file mode 100644 (file)
index 0000000..8d2e8f0
--- /dev/null
@@ -0,0 +1,19 @@
+// P3176R1 - The Oxford variadic comma
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wdeprecated" }
+
+void f1 (int...);              // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+#if __cplusplus >= 202002L
+void f2 (auto...);
+void f3 (auto......);          // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++20 } }
+#endif
+template <typename ...T>
+void f4 (T......);             // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+template <typename ...T>
+void f5 (T...);
+template <typename ...T>
+void f6 (T..., int...);                // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+void
+f7 (char...)                   // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+{
+}
diff --git a/gcc/testsuite/g++.dg/cpp26/variadic-comma3.C b/gcc/testsuite/g++.dg/cpp26/variadic-comma3.C
new file mode 100644 (file)
index 0000000..6413478
--- /dev/null
@@ -0,0 +1,5 @@
+// P3176R1 - The Oxford variadic comma
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-deprecated-variadic-comma-omission" }
+
+#include "variadic-comma1.C"
diff --git a/gcc/testsuite/g++.dg/cpp26/variadic-comma4.C b/gcc/testsuite/g++.dg/cpp26/variadic-comma4.C
new file mode 100644 (file)
index 0000000..12f0d54
--- /dev/null
@@ -0,0 +1,5 @@
+// P3176R1 - The Oxford variadic comma
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wno-deprecated" }
+
+#include "variadic-comma1.C"
diff --git a/gcc/testsuite/g++.dg/cpp26/variadic-comma5.C b/gcc/testsuite/g++.dg/cpp26/variadic-comma5.C
new file mode 100644 (file)
index 0000000..ccf3ebc
--- /dev/null
@@ -0,0 +1,19 @@
+// P3176R1 - The Oxford variadic comma
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-Wdeprecated-variadic-comma-omission" }
+
+void f1 (int...);              // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+#if __cplusplus >= 202002L
+void f2 (auto...);
+void f3 (auto......);          // { dg-warning "omission of ',' before varargs '...' is deprecated in" "" { target c++20 } }
+#endif
+template <typename ...T>
+void f4 (T......);             // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+template <typename ...T>
+void f5 (T...);
+template <typename ...T>
+void f6 (T..., int...);                // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+void
+f7 (char...)                   // { dg-warning "omission of ',' before varargs '...' is deprecated in" }
+{
+}
index 47a87bbfbd7599584bae850b440146ce0eb2cbb2..7329fa8e09051980a2d5dc0ee7eaa7ef0792a516 100644 (file)
@@ -4,7 +4,7 @@
 void sink(...);
 template <int... args> void f()
 {
-  sink ([] <int T> (int...) { return 1; }
+  sink ([] <int T> (int...) { return 1; }      // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
         .operator()<args>(args...)...); // { dg-warning "-Wmissing-template-keyword" }
 } // { dg-prune-output {expected '\)'} }
 
index 55bfc4cadb86ac1fb7fc14b1f0a90cdffc0063e3..a244c1a1b99ee1515ca950849e50529eb3550198 100644 (file)
@@ -5,7 +5,7 @@
 template <int N>
 struct T
 {
-  void foo (char const * ...) __attribute__ ((format (printf,2,3)));
+  void foo (char const * ...) __attribute__ ((format (printf,2,3)));   // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 };
 
 template struct T<3>;
index ea0e6885713192336f1b165392b98b3151927f81..9318f158c3d94eaa2068779fdbda1fe728067a3c 100644 (file)
@@ -6,7 +6,7 @@
 // Subject: bug report
 // Date: Wed, 27 Jan 1993 16:37:30 -0500
 
-extern "C" int printf(const char* ...);
+extern "C" int printf(const char* ...);        // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
 
 int     delete_counter = -1;
 
index 6309016a308d336044ab6ac0afd2c56abdd22f7a..b96be33272d3c202a93880cf0f32e483392314bb 100644 (file)
@@ -4,7 +4,7 @@
 void *ptr1, *ptr2;
 int fail = 0;
 
-extern "C" int printf(const char *...);
+extern "C" int printf(const char *...);
 
 class RWSlist { };
 
index 174b16e1eee65ad003f322f395a88e97dd44e6d5..ee207151a29b0d3519cc2153933e226c3b1ccdbb 100644 (file)
@@ -305,7 +305,7 @@ class ostream : public ios
     ostream& seekp(streampos);
     ostream& seekp(streamoff, _seek_dir);
     streampos tellp();
-    ostream& form(const char *format ...);
+    ostream& form(const char *format ...);             // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
     ostream& vform(const char *format, char*  args);
 };
 
@@ -460,7 +460,7 @@ class iostream : public ios {
        { return ((ostream*)this)->write((char*)s, n); }
     ostream& write(const void *s, int n)
        { return ((ostream*)this)->write((char*)s, n); }
-    ostream& form(const char *format ...);
+    ostream& form(const char *format ...);             // { dg-warning "omission of ',' before varargs '...' is deprecated" "" { target c++26 } }
     ostream& vform(const char *format, char*  args)
        { return ((ostream*)this)->vform(format, args); }
     ostream& seekp(streampos pos) { return ((ostream*)this)->seekp(pos); }
index a73cdc9c71ef9dbb6c317323e1330b4819cb5f9f..00a0b644331c49c729f0a16c390adc0144cb22b3 100644 (file)
@@ -94,7 +94,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using __vararg = false_type;                                     \
     };                                                                 \
   template<typename _Res, typename _Class, typename... _ArgTypes>      \
-    struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \
+    struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes..., ...) _CV _REF>        \
     : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...>              \
     {                                                                  \
       using __vararg = true_type;                                      \
@@ -145,7 +145,8 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
 
   /// Retrieve the result type for a varargs function type.
   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
-    struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
+    struct _Weak_result_type_impl<_Res(_ArgTypes...,
+                                      ...) _GLIBCXX_NOEXCEPT_QUAL>
     { typedef _Res result_type; };
 
   /// Retrieve the result type for a function pointer.
@@ -156,7 +157,7 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
   /// Retrieve the result type for a varargs function pointer.
   template<typename _Res, typename... _ArgTypes _GLIBCXX_NOEXCEPT_PARM>
     struct
-    _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
+    _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL>
     { typedef _Res result_type; };
 
   // Let _Weak_result_type_impl perform the real work.
index 743defc3cb8650c47d35f4c2e27f156bdfdf49a7..a39124df1474bef18bc8a35b872c64a654dab26e 100644 (file)
@@ -841,7 +841,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   template<typename _Ret, typename... _Args, typename... _BoundArgs>
-    struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...>
+    struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...>
     {
       static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args),
                    "Wrong number of arguments for function");
index 5e55802fba715caad0f81f529846810b7b81c615..22e156ab29857ec9b980fcdc2c7090b6456f721c 100644 (file)
@@ -235,25 +235,24 @@ namespace tr1
     struct is_function<_Res(_ArgTypes...)>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......)>
-    : public true_type { };
+    struct is_function<_Res(_ArgTypes..., ...)> : public true_type { };
   template<typename _Res, typename... _ArgTypes>
     struct is_function<_Res(_ArgTypes...) const>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const>
+    struct is_function<_Res(_ArgTypes......) const>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
     struct is_function<_Res(_ArgTypes...) volatile>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) volatile>
+    struct is_function<_Res(_ArgTypes......) volatile>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
     struct is_function<_Res(_ArgTypes...) const volatile>
     : public true_type { };
   template<typename _Res, typename... _ArgTypes>
-    struct is_function<_Res(_ArgTypes......) const volatile>
+    struct is_function<_Res(_ArgTypes......) const volatile>
     : public true_type { };
 
   // composite type traits [4.5.2].