Skip to content

Consider explicit conversions before aggregate fallback [GH #222] - #222

Open
yronglin wants to merge 3 commits into
edgcpp:mainfrom
yronglin:add_explicit_conv_before_agg_fallback
Open

yronglin wants to merge 3 commits into
edgcpp:mainfrom
yronglin:add_explicit_conv_before_agg_fallback

Conversation

@yronglin

@yronglin yronglin commented Oct 6, 2026 •

Copy link
Copy Markdown

[over.match.ref]/1.1: when binding the const float2& parameter of the copy constructor to the argument, "For direct-initialization, the permissible types for explicit conversion functions are...", the explicit operator float2() const is therefore a legitimate candidate:

  • float2(const float2&) is viable.
  • the precondition "if no constructor is viable..." in [dcl.init.general]/15.6.2.2 does not hold, so the aggregate fallback branch must not be entered.

https://godbolt.org/z/oKoMvEEdd

This PR allows explicit conversion functions when matching the implicit copy constructor during single-argument direct-initialization, preventing premature C++20 aggregate fallback rule.

Fixes #281.

@yronglin yronglin changed the title Consider explicit conversions before aggregate fallback [] Consider explicit conversions before aggregate fallback [#222] Oct 6, 2026
@yronglin yronglin changed the title Consider explicit conversions before aggregate fallback [#222] Consider explicit conversions before aggregate fallback [GH #222] Oct 6, 2026
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 <yronglin777@gmail.com>
@yronglin
yronglin force-pushed the add_explicit_conv_before_agg_fallback branch from eb4dc1c to 3251cbc Compare October 6, 2026 17:31
@danieljennings

Copy link
Copy Markdown

In case it is useful, here's a different repro of the same issue, that we hit in-house due to our use of MSVC's __m128 with parenthesized aggregate init. It looks like it's basically the same thing you're describing, and your fix appears to cover our case as well, but since I had already built this repro I felt like I might as well throw it on as a comment here:

https://godbolt.org/z/qKd6xqbqr

@nv-cmeerw

Copy link
Copy Markdown
Contributor

We still need a issue for this (via creating a discussion). The issue should also describe which language modes this applies to (C++11 or later?), or if there were any CWG issues related to this (maybe CWG 899?).

Test cases should then show the fixed behavior in the earliest language versions this change is applicable to (and also for GCC, Clang and Microsoft emulation modes - maybe something like //options:--c++11:--c++11 --gnu_version 160200:--c++11 --clang_version 230100:--ms_c++20 --microsoft_version 1950 for the test case). And if it fixes a CWG issue, there should also be a small test case in tests/tests/cwg/ with the CWG issue name.

The PR will also need a Changes entry.

Comment thread tests/tests/changes/EDGcpfe24743.sft.cpp Outdated
Comment thread src/expr.c Outdated
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]). */

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.

References to standard sections should also include the document number (e.g., N4861) for that particular reference. Ideally, it would be the first standard document with the relevant wording, so it's fairly obvious how far back the change should reach.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done. Since CWG899 introduce this rule, I have add reference to N3092.

@yronglin

yronglin commented Oct 9, 2026

Copy link
Copy Markdown
Author

Thanks for the review!

We still need a issue for this (via creating a discussion).

IIUC, we need a GitHub issue? But I don't have access to create it. Issue creation is restricted in this repository.

@nv-cmeerw

Copy link
Copy Markdown
Contributor

We still need a issue for this (via creating a discussion).
IIUC, we need a GitHub issue? But I don't have access to create it. Issue creation is restricted in this repository.

Please create an Issue Triage discussion with the details, this will then be converted to an issue.

Comment thread src/Changes
@@ -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

Comment thread src/Changes
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

Comment thread src/Changes

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).

Comment thread src/overload.c
/*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.

@@ -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).

@@ -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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider explicit conversions before aggregate fallback

3 participants