On 8/15/25 4:28 PM, Nathaniel Shead wrote:
On Fri, Aug 15, 2025 at 12:38:01PM +0200, Jakub Jelinek wrote:
Hi!

The following patch adds some testcases for the default argument (function
and template) part of the paper, making sure we diagnose multiple defargs
in the same TU and when visible in modules and DTRT when some aren't visible
and some are visible and they are equal.  Not testing when they are
different since that is IFNDR.

Tested on x86_64-linux and i686-linux, ok for trunk?

2025-08-15  Jakub Jelinek  <ja...@redhat.com>

        PR c++/121552
        * g++.dg/parse/defarg21.C: New test.
        * g++.dg/template/defarg24.C: New test.
        * g++.dg/modules/default-arg-4_a.C: New test.
        * g++.dg/modules/default-arg-4_b.C: New test.
        * g++.dg/modules/default-arg-5_a.C: New test.
        * g++.dg/modules/default-arg-5_b.C: New test.

--- gcc/testsuite/g++.dg/parse/defarg21.C.jj    2025-08-15 11:17:39.446828030 
+0200
+++ gcc/testsuite/g++.dg/parse/defarg21.C       2025-08-15 11:17:33.679900471 
+0200
@@ -0,0 +1,38 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-do compile }
+
+int f1 (int);
+int f1 (int = 42);
+int f2 (int);
+int f2 (int = 42);             // { dg-message "previous specification in 'int 
f2\\\(int\\\)' here" }
+int f2 (int = 42);             // { dg-error "default argument given for parameter 
1 of 'int f2\\\(int\\\)'" }
+int f3 (int = 42);             // { dg-message "previous specification in 'int 
f3\\\(int\\\)' here" }
+int f3 (int = 43);             // { dg-error "default argument given for parameter 
1 of 'int f3\\\(int\\\)'" }
+namespace A
+{
+  int f4 (int = 1);            // { dg-message "previous specification in 'int 
A::f4\\\(int\\\)' here" }
+  int f5 (int = 1);            // { dg-message "previous specification in 'int 
A::f5\\\(int\\\)' here" }
+}
+namespace A
+{
+  int f4 (int = 1);            // { dg-error "default argument given for parameter 
1 of 'int A::f4\\\(int\\\)'" }
+  int f5 (int = 2);            // { dg-error "default argument given for parameter 
1 of 'int A::f5\\\(int\\\)'" }
+}
+template <int N>
+int f6 (long = 42L);
+template <int N>
+int f6 (long = 42L);           // { dg-error "redeclaration of 'template<int N> int 
f6\\\(long int\\\)' may not have default arguments" }
+
+void
+foo ()
+{
+  int f7 (int = 42);           // { dg-message "previous specification in 'int 
f7\\\(int\\\)' here" }
+  int f7 (int = 42);           // { dg-error "default argument given for parameter 
1 of 'int f7\\\(int\\\)'" }
+  int f8 (int = 42);
+  {
+    int f8 (int = 42);
+    {
+      int f8 (int = 43);
+    }
+  }
+}
--- gcc/testsuite/g++.dg/template/defarg24.C.jj 2025-08-15 11:19:33.886390518 
+0200
+++ gcc/testsuite/g++.dg/template/defarg24.C    2025-08-15 11:31:12.396664456 
+0200
@@ -0,0 +1,37 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-do compile { target c++11 } }
+
+template <int N>
+int f1 (int);
+template <int N = 42>
+int f1 (int);
+template <int N>                 // { dg-message "original definition appeared 
here" }
+int f2 (int);
+template <int N = 42>
+int f2 (int);
+template <int N = 42>                    // { dg-error "redefinition of default 
argument for 'int N'" }
+int f2 (int);
+template <int N = 42>                    // { dg-message "original definition 
appeared here" }
+int f3 (int);
+template <int N = 43>                    // { dg-error "redefinition of default 
argument for 'int N'" }
+int f3 (int);
+template <typename T>
+int f4 (int);
+template <typename T = int>
+int f4 (int);
+namespace A
+{
+  template <typename T>                  // { dg-message "original definition 
appeared here" }
+  int f5 (int);
+  template <typename T = int>
+  int f5 (int);
+  template <typename T = int>            // { dg-message "original definition 
appeared here" }
+  int f6 (int);
+}
+namespace A
+{
+  template <typename T = int>            // { dg-error "redefinition of default 
argument for 'class T'" }
+  int f5 (int);
+  template <typename T = long>           // { dg-error "redefinition of default 
argument for 'class T'" }
+  int f6 (int);
+}
--- gcc/testsuite/g++.dg/modules/default-arg-4_a.C.jj   2025-08-15 
12:16:07.521139287 +0200
+++ gcc/testsuite/g++.dg/modules/default-arg-4_a.C      2025-08-15 
12:31:11.313828020 +0200
@@ -0,0 +1,19 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi M }
+
+module;
+
+int foo (int i = 42);
+template <typename T, typename U = int>
+int bar ();
+template <typename T, int N = 42>
+int baz ();
+
+export module M;
+
+export inline int
+qux ()
+{
+  return foo () + bar <int> () + baz <int> ();
+}
--- gcc/testsuite/g++.dg/modules/default-arg-4_b.C.jj   2025-08-15 
12:16:12.027082865 +0200
+++ gcc/testsuite/g++.dg/modules/default-arg-4_b.C      2025-08-15 
12:29:25.186152954 +0200
@@ -0,0 +1,36 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int
+foo (int i = 42)
+{
+  return i;
+}
+
+template <typename T, typename U = int>
+int
+bar ()
+{
+  return sizeof (U);
+}
+
+template <typename T, int N = 42>
+int
+baz ()
+{
+  return N;
+}
+
+int
+main ()
+{
+  if (foo () + bar <int> () + baz <int> () != qux ())
+    __builtin_abort ();
+  if (foo () != foo (42)
+      || bar <int> () != bar <int, int> ()
+      || baz <int> () != baz <int, 42> ())
+    __builtin_abort ();
+}
--- gcc/testsuite/g++.dg/modules/default-arg-5_a.C.jj   2025-08-15 
12:16:07.521139287 +0200
+++ gcc/testsuite/g++.dg/modules/default-arg-5_a.C      2025-08-15 
12:31:20.149717714 +0200
@@ -0,0 +1,23 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi M }
+
+module;
+
+int foo (int i = 42);
+template <typename T, typename U = int>
+int bar ();
+template <typename T, int N = 42>
+int baz ();
+
+export module M;
+
+export inline int
+qux ()
+{
+  return foo () + bar <int> () + baz <int> ();
+}
+
+export using ::foo;
+export using ::bar;
+export using ::baz;
--- gcc/testsuite/g++.dg/modules/default-arg-5_b.C.jj   2025-08-15 
12:16:12.027082865 +0200
+++ gcc/testsuite/g++.dg/modules/default-arg-5_b.C      2025-08-15 
12:28:39.750720402 +0200
@@ -0,0 +1,35 @@
+// C++20 P1766R1 - Mitigating minor modules maladies
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int
+foo (int i = 42)                       // { dg-error "default argument given for 
parameter 1 of 'int foo\\\(int\\\)'" }

I don't think this (or the following in this file) should be errors; we
error currently because we don't implement textual deduplication
(PR99000), but since the default arguments are the same, from the
current wording this should be OK as far as I understand it.

In particular, the default argument definition here is in a different TU
from that of the definition in M, so [basic.def.odr] p2 doesn't apply.
We test this the other way around in modules/default-arg-3.

(Note that the wording in the C++20 WD is not the same as the wording
diff given in p1766r1, it seems to have been adjusted before C++20 was
published: https://timsong-cpp.github.io/cppwp/n4861/basic.def.odr#1)

Let me know if I've misunderstood something here.

No, I think you're right.  So those should be dg-bogus xfail instead.

Jason

Reply via email to