From 3251cbc77e8c6c9fa28dfbfa8168aabd6987b282 Mon Sep 17 00:00:00 2001 From: Yihan Wang Date: Mon, 5 Oct 2026 10:50:33 -0700 Subject: [PATCH 1/3] Consider explicit conversions before aggregate fallback [] Allow explicit conversion functions when matching the implicit copy constructor during single-argument direct-initialization, preventing premature C++20 aggregate fallback. Extend EDGcpfe24743 to cover explicit conversion functions. Signed-off-by: Yihan Wang --- src/expr.c | 6 +++++- src/overload.c | 4 +++- tests/tests/changes/EDGcpfe24743.sft.cpp | 6 ++++++ .../SemaCXX/.cxx2a-explicit-bool.rto/default.2.1.txt | 10 +--------- .../clang/cpp/SemaCXX/.explicit.rto/default.2.1.txt | 10 +--------- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/expr.c b/src/expr.c index fe8a6d57cd..adcc10de30 100644 --- a/src/expr.c +++ b/src/expr.c @@ -30702,11 +30702,15 @@ parentheses do not themselves correspond to aggregate initialization). an_arg_match_summary arg_match; an_operand opnd; clear_arg_match_summary(&arg_match); + /* When matching the first reference parameter of a copy constructor + called with one argument in a direct-initialization context, explicit + conversion functions are considered ([over.match.copy]). */ prep_list_initializer(arg_list, dest_type, /*is_direct_init=*/TRUE, /*check_narrowing=*/FALSE, /*warning_on_narrowing=*/FALSE, CCO_CAST | CCO_FUNC_NOTATION_CAST | - CCO_EXPLICIT_CAST | CCO_DIRECT_INITIALIZATION, + CCO_EXPLICIT_CAST | CCO_DIRECT_INITIALIZATION | + CCO_ALLOW_EXPLICIT_CONV_FUNCTIONS, /*fill_in_dtor=*/TRUE, /*force_temp=*/FALSE, /*make_lvalue_temp=*/FALSE, &opnd, (an_init_state*)NULL, &arg_match); diff --git a/src/overload.c b/src/overload.c index 4eafe2f719..6592201c34 100644 --- a/src/overload.c +++ b/src/overload.c @@ -27542,7 +27542,9 @@ will be an lvalue instead of the usual prvalue. (a_param_type_ptr)NULL, /*param_type_is_deduced=*/FALSE, try_user_conversions_in_ovl_res, - /*allow_expl_conv_funcs=*/FALSE, + /*allow_expl_conv_funcs=*/ + (conv_context & + CCO_ALLOW_EXPLICIT_CONV_FUNCTIONS) != 0, arg_match); } /* if */ } else { diff --git a/tests/tests/changes/EDGcpfe24743.sft.cpp b/tests/tests/changes/EDGcpfe24743.sft.cpp index ea0022a590..232e6aeba6 100644 --- a/tests/tests/changes/EDGcpfe24743.sft.cpp +++ b/tests/tests/changes/EDGcpfe24743.sft.cpp @@ -15,3 +15,9 @@ struct S { operator D() const; }; void g(S p) { D d(p); // Previously an error. Now okay. } + +struct ExplicitS { explicit operator D() const; }; +D h(ExplicitS p) { + D d(p); // Previously an error in C++20 mode. Now okay. + return D(p); // Likewise. +} diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2a-explicit-bool.rto/default.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2a-explicit-bool.rto/default.2.1.txt index 61b48306c1..e3487904a6 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.cxx2a-explicit-bool.rto/default.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.cxx2a-explicit-bool.rto/default.2.1.txt @@ -476,14 +476,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers Y y2 = z; // expected-error {{no viable conversion}} ^ -"Test_name.c", line 530: error: too many initializer values - Y y2b(z); - ^ - -"Test_name.c", line 532: error: too many initializer values - Y y4 = Y(z); - ^ - "Test_name.c", line 540: error: no suitable user-defined conversion from "conversion3::Z" to "const conversion3::Y" exists const Y& y6 = z; // expected-error {{no viable conversion}} ^ @@ -683,4 +675,4 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers explicit(ptr) S(long); // expected-error {{conversion from 'const int *' to 'bool' is not allowed in a converted constant expression}} ^ -121 errors detected in the compilation of "Test_name.c". +119 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/imported/clang/cpp/SemaCXX/.explicit.rto/default.2.1.txt b/tests/tests/imported/clang/cpp/SemaCXX/.explicit.rto/default.2.1.txt index ededac4caa..0428590258 100644 --- a/tests/tests/imported/clang/cpp/SemaCXX/.explicit.rto/default.2.1.txt +++ b/tests/tests/imported/clang/cpp/SemaCXX/.explicit.rto/default.2.1.txt @@ -23,14 +23,6 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers Y y2 = z; // expected-error {{no viable conversion from 'Z' to 'Y'}} ^ -"Test_name.c", line 90: error: too many initializer values - Y y2b(z); - ^ - -"Test_name.c", line 92: error: too many initializer values - Y y4 = Y(z); - ^ - "Test_name.c", line 100: error: no suitable user-defined conversion from "Z" to "const Y" exists const Y& y6 = z; // expected-error {{no viable conversion from 'Z' to 'const Y'}} ^ @@ -171,4 +163,4 @@ fe_only -DTEST_NUMBER=2 --clang -tused -e 200 --no_wrap_diagnostics --clang_vers switch(EC){} ^ -31 errors detected in the compilation of "Test_name.c". +29 errors detected in the compilation of "Test_name.c". From 3fc9bca9dfedf590eaf4422a091172a709473164 Mon Sep 17 00:00:00 2001 From: Yihan Wang Date: Mon, 12 Oct 2026 08:12:18 -0700 Subject: [PATCH 2/3] Address review comments and add more tests [GH #281] --- src/Changes | 19 ++++++++++++++++ src/expr.c | 3 ++- .../tests/changes/.GH281.rto/default.1.1.txt | 1 + .../tests/changes/.GH281.rto/default.2.1.txt | 1 + .../tests/changes/.GH281.rto/default.3.1.txt | 1 + .../tests/changes/.GH281.rto/default.4.1.txt | 1 + .../tests/changes/.GH281.rto/default.5.1.txt | 1 + .../tests/changes/.GH281.rto/default.6.1.txt | 1 + .../tests/changes/.GH281.rto/default.7.1.txt | 1 + tests/tests/changes/EDGcpfe24743.sft.cpp | 6 ----- tests/tests/changes/GH281.sft.cpp | 20 +++++++++++++++++ tests/tests/cwg/.899.rto/default.1.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.2.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.3.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.4.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.5.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.6.1.txt | 10 +++++++++ tests/tests/cwg/.899.rto/default.7.1.txt | 10 +++++++++ tests/tests/cwg/899.sft.cpp | 22 +++++++++++++++++++ 19 files changed, 140 insertions(+), 7 deletions(-) create mode 100644 tests/tests/changes/.GH281.rto/default.1.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.2.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.3.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.4.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.5.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.6.1.txt create mode 100644 tests/tests/changes/.GH281.rto/default.7.1.txt create mode 100644 tests/tests/changes/GH281.sft.cpp create mode 100644 tests/tests/cwg/.899.rto/default.1.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.2.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.3.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.4.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.5.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.6.1.txt create mode 100644 tests/tests/cwg/.899.rto/default.7.1.txt create mode 100644 tests/tests/cwg/899.sft.cpp diff --git a/src/Changes b/src/Changes index 79bcd59a6c..1bd4845ddf 100644 --- a/src/Changes +++ b/src/Changes @@ -1,3 +1,22 @@ +10/12/26 [GH #281] +Explicit conversion functions before parenthesized aggregate initialization + +The front end could incorrectly attempt parenthesized aggregate initialization +instead of considering an explicit conversion function when directly +initializing an aggregate in C++20 mode. For example: + + struct D { float x, y; }; + struct S { explicit operator D() const; }; + D f(S s) { + D d(s); // Previously an error in C++20 mode. Now okay. + return D(s); // Likewise. + } + +That is now fixed. The rule allowing explicit conversion functions in this +context comes from Core issue 899 and applies in C++11 and later modes. The +failure occurred when C++20 parenthesized aggregate initialization was enabled. + + 10/1/26 [GH #197] Deducing noexcept-specifiers diff --git a/src/expr.c b/src/expr.c index adcc10de30..fbe143f994 100644 --- a/src/expr.c +++ b/src/expr.c @@ -30704,7 +30704,8 @@ parentheses do not themselves correspond to aggregate initialization). clear_arg_match_summary(&arg_match); /* When matching the first reference parameter of a copy constructor called with one argument in a direct-initialization context, explicit - conversion functions are considered ([over.match.copy]). */ + conversion functions are considered (N3092 [over.match.copy]/1, + Core issue 899). */ prep_list_initializer(arg_list, dest_type, /*is_direct_init=*/TRUE, /*check_narrowing=*/FALSE, /*warning_on_narrowing=*/FALSE, diff --git a/tests/tests/changes/.GH281.rto/default.1.1.txt b/tests/tests/changes/.GH281.rto/default.1.1.txt new file mode 100644 index 0000000000..fcf5b546e4 --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.2.1.txt b/tests/tests/changes/.GH281.rto/default.2.1.txt new file mode 100644 index 0000000000..480ced1860 --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.3.1.txt b/tests/tests/changes/.GH281.rto/default.3.1.txt new file mode 100644 index 0000000000..fcf16ce89d --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.4.1.txt b/tests/tests/changes/.GH281.rto/default.4.1.txt new file mode 100644 index 0000000000..7f68c48fcc --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.5.1.txt b/tests/tests/changes/.GH281.rto/default.5.1.txt new file mode 100644 index 0000000000..5411ee9e60 --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.6.1.txt b/tests/tests/changes/.GH281.rto/default.6.1.txt new file mode 100644 index 0000000000..87a47aca25 --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c diff --git a/tests/tests/changes/.GH281.rto/default.7.1.txt b/tests/tests/changes/.GH281.rto/default.7.1.txt new file mode 100644 index 0000000000..ab7537ac29 --- /dev/null +++ b/tests/tests/changes/.GH281.rto/default.7.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c diff --git a/tests/tests/changes/EDGcpfe24743.sft.cpp b/tests/tests/changes/EDGcpfe24743.sft.cpp index 232e6aeba6..ea0022a590 100644 --- a/tests/tests/changes/EDGcpfe24743.sft.cpp +++ b/tests/tests/changes/EDGcpfe24743.sft.cpp @@ -15,9 +15,3 @@ struct S { operator D() const; }; void g(S p) { D d(p); // Previously an error. Now okay. } - -struct ExplicitS { explicit operator D() const; }; -D h(ExplicitS p) { - D d(p); // Previously an error in C++20 mode. Now okay. - return D(p); // Likewise. -} diff --git a/tests/tests/changes/GH281.sft.cpp b/tests/tests/changes/GH281.sft.cpp new file mode 100644 index 0000000000..4b5569e7bb --- /dev/null +++ b/tests/tests/changes/GH281.sft.cpp @@ -0,0 +1,20 @@ +//type:fp +//options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 +//options_all:-tused +//remark:Explicit conversion functions before aggregate fallback [GH #281] +// Core issue 899 permits these conversions in C++11 and later. Previously, +// C++20 parenthesized aggregate initialization caused spurious errors. + +struct D { float x, y; }; +struct S { + float x, y; + explicit constexpr operator D() const { return D{x, y}; } +}; + +D f(S s) { + D d(s); // Previously an error in C++20 mode. Now okay. + return D(s); // Likewise. +} + +constexpr S s = {1.0f, 2.0f}; +static_assert(D(s).x == 1.0f && D(s).y == 2.0f, "functional cast"); diff --git a/tests/tests/cwg/.899.rto/default.1.1.txt b/tests/tests/cwg/.899.rto/default.1.1.txt new file mode 100644 index 0000000000..04bdacfb33 --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.1.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.2.1.txt b/tests/tests/cwg/.899.rto/default.2.1.txt new file mode 100644 index 0000000000..22089b6dc8 --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.2.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.3.1.txt b/tests/tests/cwg/.899.rto/default.3.1.txt new file mode 100644 index 0000000000..7dc696587f --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.3.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.4.1.txt b/tests/tests/cwg/.899.rto/default.4.1.txt new file mode 100644 index 0000000000..c88edeae40 --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.4.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.5.1.txt b/tests/tests/cwg/.899.rto/default.5.1.txt new file mode 100644 index 0000000000..cdaea3d1d1 --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.5.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.6.1.txt b/tests/tests/cwg/.899.rto/default.6.1.txt new file mode 100644 index 0000000000..cb2aec38b8 --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.6.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/.899.rto/default.7.1.txt b/tests/tests/cwg/.899.rto/default.7.1.txt new file mode 100644 index 0000000000..09e46c8a0e --- /dev/null +++ b/tests/tests/cwg/.899.rto/default.7.1.txt @@ -0,0 +1,10 @@ +fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c +"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists + int i = a; // Error: copy-initialization. + ^ + +"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists + C c = a; // Error: copy-initialization. + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/cwg/899.sft.cpp b/tests/tests/cwg/899.sft.cpp new file mode 100644 index 0000000000..9790365b97 --- /dev/null +++ b/tests/tests/cwg/899.sft.cpp @@ -0,0 +1,22 @@ +//type:fn +//options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 +//options_all:-tused +//remark:Core issue 899: Explicit conversion functions in direct class initialization + +struct C { }; +struct A { + explicit operator int() const; + explicit operator C() const; +}; + +struct B { + int i; + B(const A& a): i(a) { } // Okay. +}; + +void f(A a) { + int i = a; // Error: copy-initialization. + int j(a); // Okay: direct-initialization. + C c = a; // Error: copy-initialization. + C c2(a); // Okay: direct-initialization (Core issue 899). +} From a6befe6be72ab7b1a138686151544a742cc07770 Mon Sep 17 00:00:00 2001 From: yronglin Date: Fri, 16 Oct 2026 01:15:55 +0800 Subject: [PATCH 3/3] Refine tests [GH #222] Signed-off-by: yronglin --- src/Changes | 9 ++++--- src/overload.c | 7 ++++-- tests/tests/changes/GH281.sft.cpp | 16 ++----------- tests/tests/cwg/.cwg899.rto/default.1.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.2.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.3.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.4.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.5.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.6.1.txt | 1 + tests/tests/cwg/.cwg899.rto/default.7.1.txt | 1 + .../default.1.1.txt | 4 ++-- .../default.2.1.txt | 4 ++-- .../default.3.1.txt | 4 ++-- .../default.4.1.txt | 4 ++-- .../default.5.1.txt | 4 ++-- .../default.6.1.txt | 4 ++-- .../default.7.1.txt | 4 ++-- .../tests/cwg/{899.sft.cpp => cwg899.sft.cpp} | 4 +--- tests/tests/cwg/cwg899b.sft.cpp | 15 ++++++++++++ .../regressions/.gh-222.rto/default.1.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.2.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.3.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.4.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.5.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.6.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222.rto/default.7.1.txt | 24 +++++++++++++++++++ .../regressions/.gh-222a.rto/default.1.1.txt | 1 + .../regressions/.gh-222a.rto/default.2.1.txt | 1 + .../regressions/.gh-222a.rto/default.3.1.txt | 1 + .../regressions/.gh-222a.rto/default.4.1.txt | 1 + .../regressions/.gh-222a.rto/default.5.1.txt | 1 + .../regressions/.gh-222a.rto/default.6.1.txt | 1 + .../regressions/.gh-222a.rto/default.7.1.txt | 1 + tests/tests/regressions/gh-222.sft.cpp | 23 ++++++++++++++++++ tests/tests/regressions/gh-222a.sft.cpp | 20 ++++++++++++++++ 35 files changed, 266 insertions(+), 38 deletions(-) create mode 100644 tests/tests/cwg/.cwg899.rto/default.1.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.2.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.3.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.4.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.5.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.6.1.txt create mode 100644 tests/tests/cwg/.cwg899.rto/default.7.1.txt rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.1.1.txt (68%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.2.1.txt (70%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.3.1.txt (70%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.4.1.txt (68%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.5.1.txt (70%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.6.1.txt (70%) rename tests/tests/cwg/{.899.rto => .cwg899b.rto}/default.7.1.txt (70%) rename tests/tests/cwg/{899.sft.cpp => cwg899.sft.cpp} (85%) create mode 100644 tests/tests/cwg/cwg899b.sft.cpp create mode 100644 tests/tests/regressions/.gh-222.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.5.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.6.1.txt create mode 100644 tests/tests/regressions/.gh-222.rto/default.7.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.1.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.2.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.3.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.4.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.5.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.6.1.txt create mode 100644 tests/tests/regressions/.gh-222a.rto/default.7.1.txt create mode 100644 tests/tests/regressions/gh-222.sft.cpp create mode 100644 tests/tests/regressions/gh-222a.sft.cpp diff --git a/src/Changes b/src/Changes index 62bc9a6a7b..722e31552b 100644 --- a/src/Changes +++ b/src/Changes @@ -1,3 +1,5 @@ +Version 7.1 + 10/12/26 [GH #281] Explicit conversion functions before parenthesized aggregate initialization @@ -7,15 +9,12 @@ initializing an aggregate in C++20 mode. For example: struct D { float x, y; }; struct S { explicit operator D() const; }; - D f(S s) { - D d(s); // Previously an error in C++20 mode. Now okay. - return D(s); // Likewise. - } + D d(S{}); // Previously an error in C++20 mode. Now okay. That is now fixed. The rule allowing explicit conversion functions in this context comes from Core issue 899 and applies in C++11 and later modes. The failure occurred when C++20 parenthesized aggregate initialization was enabled. -Version 7.1 + 10/9/26 [GH #27] Clearer diagnostic when auto is deduced from an incomplete type diff --git a/src/overload.c b/src/overload.c index 054c8fb3f4..1922ecfd77 100644 --- a/src/overload.c +++ b/src/overload.c @@ -27545,14 +27545,17 @@ will be an lvalue instead of the usual prvalue. in this context. */ arg_match_err = TRUE; } else { + /* For this tentative match, explicit conversion functions are only + considered for direct initialization. In particular, a temporary + created for a braced reference argument is copy-list-initialized. */ determine_arg_match_level(operand_of_arg_list_elem(icp), (a_type_ptr)NULL, dest_type, (a_param_type_ptr)NULL, /*param_type_is_deduced=*/FALSE, try_user_conversions_in_ovl_res, - /*allow_expl_conv_funcs=*/ - (conv_context & + is_direct_init && + (conv_context & CCO_ALLOW_EXPLICIT_CONV_FUNCTIONS) != 0, arg_match); } /* if */ diff --git a/tests/tests/changes/GH281.sft.cpp b/tests/tests/changes/GH281.sft.cpp index 4b5569e7bb..5cd30cb122 100644 --- a/tests/tests/changes/GH281.sft.cpp +++ b/tests/tests/changes/GH281.sft.cpp @@ -2,19 +2,7 @@ //options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 //options_all:-tused //remark:Explicit conversion functions before aggregate fallback [GH #281] -// Core issue 899 permits these conversions in C++11 and later. Previously, -// C++20 parenthesized aggregate initialization caused spurious errors. struct D { float x, y; }; -struct S { - float x, y; - explicit constexpr operator D() const { return D{x, y}; } -}; - -D f(S s) { - D d(s); // Previously an error in C++20 mode. Now okay. - return D(s); // Likewise. -} - -constexpr S s = {1.0f, 2.0f}; -static_assert(D(s).x == 1.0f && D(s).y == 2.0f, "functional cast"); +struct S { explicit operator D() const; }; +D d(S{}); // Error, now okay. diff --git a/tests/tests/cwg/.cwg899.rto/default.1.1.txt b/tests/tests/cwg/.cwg899.rto/default.1.1.txt new file mode 100644 index 0000000000..fcf5b546e4 --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.2.1.txt b/tests/tests/cwg/.cwg899.rto/default.2.1.txt new file mode 100644 index 0000000000..480ced1860 --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.3.1.txt b/tests/tests/cwg/.cwg899.rto/default.3.1.txt new file mode 100644 index 0000000000..fcf16ce89d --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.4.1.txt b/tests/tests/cwg/.cwg899.rto/default.4.1.txt new file mode 100644 index 0000000000..7f68c48fcc --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.5.1.txt b/tests/tests/cwg/.cwg899.rto/default.5.1.txt new file mode 100644 index 0000000000..5411ee9e60 --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.6.1.txt b/tests/tests/cwg/.cwg899.rto/default.6.1.txt new file mode 100644 index 0000000000..87a47aca25 --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c diff --git a/tests/tests/cwg/.cwg899.rto/default.7.1.txt b/tests/tests/cwg/.cwg899.rto/default.7.1.txt new file mode 100644 index 0000000000..ab7537ac29 --- /dev/null +++ b/tests/tests/cwg/.cwg899.rto/default.7.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c diff --git a/tests/tests/cwg/.899.rto/default.1.1.txt b/tests/tests/cwg/.cwg899b.rto/default.1.1.txt similarity index 68% rename from tests/tests/cwg/.899.rto/default.1.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.1.1.txt index 04bdacfb33..72e0638066 100644 --- a/tests/tests/cwg/.899.rto/default.1.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.1.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.2.1.txt b/tests/tests/cwg/.cwg899b.rto/default.2.1.txt similarity index 70% rename from tests/tests/cwg/.899.rto/default.2.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.2.1.txt index 22089b6dc8..84a180bab8 100644 --- a/tests/tests/cwg/.899.rto/default.2.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.2.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.3.1.txt b/tests/tests/cwg/.cwg899b.rto/default.3.1.txt similarity index 70% rename from tests/tests/cwg/.899.rto/default.3.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.3.1.txt index 7dc696587f..ccd4f7abc8 100644 --- a/tests/tests/cwg/.899.rto/default.3.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.3.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.4.1.txt b/tests/tests/cwg/.cwg899b.rto/default.4.1.txt similarity index 68% rename from tests/tests/cwg/.899.rto/default.4.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.4.1.txt index c88edeae40..ebc0b08ccf 100644 --- a/tests/tests/cwg/.899.rto/default.4.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.4.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.5.1.txt b/tests/tests/cwg/.cwg899b.rto/default.5.1.txt similarity index 70% rename from tests/tests/cwg/.899.rto/default.5.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.5.1.txt index cdaea3d1d1..39870328d4 100644 --- a/tests/tests/cwg/.899.rto/default.5.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.5.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.6.1.txt b/tests/tests/cwg/.cwg899b.rto/default.6.1.txt similarity index 70% rename from tests/tests/cwg/.899.rto/default.6.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.6.1.txt index cb2aec38b8..1b7747133d 100644 --- a/tests/tests/cwg/.899.rto/default.6.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.6.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/.899.rto/default.7.1.txt b/tests/tests/cwg/.cwg899b.rto/default.7.1.txt similarity index 70% rename from tests/tests/cwg/.899.rto/default.7.1.txt rename to tests/tests/cwg/.cwg899b.rto/default.7.1.txt index 09e46c8a0e..f996322ca7 100644 --- a/tests/tests/cwg/.899.rto/default.7.1.txt +++ b/tests/tests/cwg/.cwg899b.rto/default.7.1.txt @@ -1,9 +1,9 @@ fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c -"Test_name.c", line 18: error: no suitable conversion function from "A" to "int" exists +"Test_name.c", line 13: error: no suitable conversion function from "A" to "int" exists int i = a; // Error: copy-initialization. ^ -"Test_name.c", line 20: error: no suitable user-defined conversion from "A" to "C" exists +"Test_name.c", line 14: error: no suitable user-defined conversion from "A" to "C" exists C c = a; // Error: copy-initialization. ^ diff --git a/tests/tests/cwg/899.sft.cpp b/tests/tests/cwg/cwg899.sft.cpp similarity index 85% rename from tests/tests/cwg/899.sft.cpp rename to tests/tests/cwg/cwg899.sft.cpp index 9790365b97..2652c2d6e6 100644 --- a/tests/tests/cwg/899.sft.cpp +++ b/tests/tests/cwg/cwg899.sft.cpp @@ -1,4 +1,4 @@ -//type:fn +//type:fp //options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 //options_all:-tused //remark:Core issue 899: Explicit conversion functions in direct class initialization @@ -15,8 +15,6 @@ struct B { }; void f(A a) { - int i = a; // Error: copy-initialization. int j(a); // Okay: direct-initialization. - C c = a; // Error: copy-initialization. C c2(a); // Okay: direct-initialization (Core issue 899). } diff --git a/tests/tests/cwg/cwg899b.sft.cpp b/tests/tests/cwg/cwg899b.sft.cpp new file mode 100644 index 0000000000..7c8fe40867 --- /dev/null +++ b/tests/tests/cwg/cwg899b.sft.cpp @@ -0,0 +1,15 @@ +//type:fn +//options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 +//options_all:-tused +//remark:Core issue 899: Explicit conversion functions in copy-initialization + +struct C { }; +struct A { + explicit operator int() const; + explicit operator C() const; +}; + +void f(A a) { + int i = a; // Error: copy-initialization. + C c = a; // Error: copy-initialization. +} diff --git a/tests/tests/regressions/.gh-222.rto/default.1.1.txt b/tests/tests/regressions/.gh-222.rto/default.1.1.txt new file mode 100644 index 0000000000..df7d300732 --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.1.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.2.1.txt b/tests/tests/regressions/.gh-222.rto/default.2.1.txt new file mode 100644 index 0000000000..22583872da --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.2.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.3.1.txt b/tests/tests/regressions/.gh-222.rto/default.3.1.txt new file mode 100644 index 0000000000..7ab4d9d2e6 --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.3.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.4.1.txt b/tests/tests/regressions/.gh-222.rto/default.4.1.txt new file mode 100644 index 0000000000..bb2c81690f --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.4.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.5.1.txt b/tests/tests/regressions/.gh-222.rto/default.5.1.txt new file mode 100644 index 0000000000..12a3017a98 --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.5.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.6.1.txt b/tests/tests/regressions/.gh-222.rto/default.6.1.txt new file mode 100644 index 0000000000..9b2b9f38e8 --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.6.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222.rto/default.7.1.txt b/tests/tests/regressions/.gh-222.rto/default.7.1.txt new file mode 100644 index 0000000000..0b8d2c868e --- /dev/null +++ b/tests/tests/regressions/.gh-222.rto/default.7.1.txt @@ -0,0 +1,24 @@ +fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c +"Test_name.c", line 15: error: no instance of overloaded function "f" matches the argument list + argument types are: ({...}) + int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. + ^ +"Test_name.c", line 7: note: function "f(int *)" does not match because argument #1 does not match parameter + int f(int*); + ^ +"Test_name.c", line 6: note: function "f(int &&)" does not match because argument #1 does not match parameter + int f(int&&); + ^ + +"Test_name.c", line 16: error: no instance of overloaded function "g" matches the argument list + argument types are: ({...}) + int j = g({A{}}); // Likewise for a const lvalue reference. + ^ +"Test_name.c", line 9: note: function "g(int *)" does not match because argument #1 does not match parameter + int g(int*); + ^ +"Test_name.c", line 8: note: function "g(const int &)" does not match because argument #1 does not match parameter + int g(const int&); + ^ + +2 errors detected in the compilation of "Test_name.c". diff --git a/tests/tests/regressions/.gh-222a.rto/default.1.1.txt b/tests/tests/regressions/.gh-222a.rto/default.1.1.txt new file mode 100644 index 0000000000..fcf5b546e4 --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.1.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.2.1.txt b/tests/tests/regressions/.gh-222a.rto/default.2.1.txt new file mode 100644 index 0000000000..480ced1860 --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.2.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.3.1.txt b/tests/tests/regressions/.gh-222a.rto/default.3.1.txt new file mode 100644 index 0000000000..fcf16ce89d --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.3.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.4.1.txt b/tests/tests/regressions/.gh-222a.rto/default.4.1.txt new file mode 100644 index 0000000000..7f68c48fcc --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.4.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.5.1.txt b/tests/tests/regressions/.gh-222a.rto/default.5.1.txt new file mode 100644 index 0000000000..5411ee9e60 --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.5.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.6.1.txt b/tests/tests/regressions/.gh-222a.rto/default.6.1.txt new file mode 100644 index 0000000000..87a47aca25 --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.6.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c diff --git a/tests/tests/regressions/.gh-222a.rto/default.7.1.txt b/tests/tests/regressions/.gh-222a.rto/default.7.1.txt new file mode 100644 index 0000000000..ab7537ac29 --- /dev/null +++ b/tests/tests/regressions/.gh-222a.rto/default.7.1.txt @@ -0,0 +1 @@ +fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c diff --git a/tests/tests/regressions/gh-222.sft.cpp b/tests/tests/regressions/gh-222.sft.cpp new file mode 100644 index 0000000000..bb5ef7cbfe --- /dev/null +++ b/tests/tests/regressions/gh-222.sft.cpp @@ -0,0 +1,23 @@ +//type:fn +//options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 +//options_all:-tused +//remark:Explicit conversions are not viable for braced reference arguments + +int f(int&&); +int f(int*); +int g(const int&); +int g(int*); + +struct A { + explicit operator int() const; +}; + +int i = f({A{}}); // Error: cannot copy-list-initialize the temporary int. +int j = g({A{}}); // Likewise for a const lvalue reference. + +struct B { + operator int() const; +}; + +int k = f({B{}}); // Okay: implicit conversions are still considered. +int l = g({B{}}); diff --git a/tests/tests/regressions/gh-222a.sft.cpp b/tests/tests/regressions/gh-222a.sft.cpp new file mode 100644 index 0000000000..4b5569e7bb --- /dev/null +++ b/tests/tests/regressions/gh-222a.sft.cpp @@ -0,0 +1,20 @@ +//type:fp +//options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--c++20:--c++20 --gnu_version 160200:--c++20 --clang_version 230100:--ms_c++20 --microsoft_version 1950 +//options_all:-tused +//remark:Explicit conversion functions before aggregate fallback [GH #281] +// Core issue 899 permits these conversions in C++11 and later. Previously, +// C++20 parenthesized aggregate initialization caused spurious errors. + +struct D { float x, y; }; +struct S { + float x, y; + explicit constexpr operator D() const { return D{x, y}; } +}; + +D f(S s) { + D d(s); // Previously an error in C++20 mode. Now okay. + return D(s); // Likewise. +} + +constexpr S s = {1.0f, 2.0f}; +static_assert(D(s).x == 1.0f && D(s).y == 2.0f, "functional cast");