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\\\)'" } +{ + return i; +} + +template <typename T, typename U = int> // { dg-error "redefinition of default argument for 'class U'" } +int +bar () +{ + return sizeof (U); +} + +template <typename T, int N = 42> // { dg-error "redefinition of default argument for 'int N'" } +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 (); +} Jakub