Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions src/Changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
10/12/26 [GH #281]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes entry should be added after the "Version 7.1" header

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To keep the Changes example as short as possible, you can just use D d(S{}); instead of the f function body

}

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following example is now accepted in C++11 mode:

int f(int &&);
int f(int *);

struct A {
  explicit operator int() const;
};

int i = f({A{}});

Seems to be related to EDGcpfe/21369. g++/clang don't accept this. Needs some more investigation, and should be mentioned in the Changes entry (if we want to keep that behaviour).

Version 7.1

10/9/26 [GH #27]
Expand Down
7 changes: 6 additions & 1 deletion src/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -30702,11 +30702,16 @@ 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 (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,
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);
Expand Down
4 changes: 3 additions & 1 deletion src/overload.c
Original file line number Diff line number Diff line change
Expand Up @@ -27551,7 +27551,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=*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That comment line can now be removed, as the expression is now sufficiently clear on its own.

(conv_context &
CCO_ALLOW_EXPLICIT_CONV_FUNCTIONS) != 0,
arg_match);
} /* if */
} else {
Expand Down
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=1 -tused --c++11 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=2 -tused --c++11 --gnu_version 160200 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=3 -tused --c++11 --clang_version 230100 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.4.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=4 -tused --c++20 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.5.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=5 -tused --c++20 --gnu_version 160200 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.6.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=6 -tused --c++20 --clang_version 230100 Test_name.c
1 change: 1 addition & 0 deletions tests/tests/changes/.GH281.rto/default.7.1.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fe_only -DTEST_NUMBER=7 -tused --ms_c++20 --microsoft_version 1950 Test_name.c
20 changes: 20 additions & 0 deletions tests/tests/changes/GH281.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//type:fp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes directory should just contain the Changes examples, and the regressions directory should be used for additional tests.

//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");
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.1.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.2.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.3.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.4.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.5.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.6.1.txt
Original file line number Diff line number Diff line change
@@ -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".
10 changes: 10 additions & 0 deletions tests/tests/cwg/.899.rto/default.7.1.txt
Original file line number Diff line number Diff line change
@@ -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".
22 changes: 22 additions & 0 deletions tests/tests/cwg/899.sft.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//type:fn

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename to cwg899.sft.cpp (as that's the predominant naming convention for CWG tests) and split the negative cases into a separate file (cwg899b.sft.cpp).

//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).
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<true>" to "const conversion3::Y" exists
const Y& y6 = z; // expected-error {{no viable conversion}}
^
Expand Down Expand Up @@ -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".
Original file line number Diff line number Diff line change
Expand Up @@ -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'}}
^
Expand Down Expand Up @@ -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".