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.

Nathaniel

Reply via email to