Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang disallows brace elision in designated initializer of member array when constructing a temporary function parameter #121553

Open
wangbo15 opened this issue Jan 3, 2025 · 2 comments
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" diverges-from:edg Does the clang frontend diverge from edg compiler diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue

Comments

@wangbo15
Copy link

wangbo15 commented Jan 3, 2025

Clang rejects the following valid code:

struct B {
  int b[10];
};

struct C
{
  C (B x) {}
};

//OK
//B bb{.b = 42};
//OK
//C c ({.b = {42}});
//OK
//C c({42});
//Fails
C c ({.b = 42});

The question seems to be related to both the designated initializer and the brace elision operation because separately removing the former( like C c({42}); ) or the latter( like C c ({.b = {42}}); ) can both make the code compile.

GCC, MSVC, and EDG always accept it.

The diagnostic of clang:

<source>:17:3: error: no matching constructor for initialization of 'C'
   17 | C c ({.b = 42});
      |   ^  ~~~~~~~~~
<source>:5:8: note: candidate constructor (the implicit copy constructor) not viable: cannot convert initializer list argument to 'const C'
    5 | struct C
      |        ^
<source>:5:8: note: candidate constructor (the implicit move constructor) not viable: cannot convert initializer list argument to 'C'
    5 | struct C
      |        ^
<source>:7:3: note: candidate constructor not viable: cannot convert initializer list argument to 'B'
    7 |   C (B x) {}
      |   ^  ~~~
1 error generated.

https://godbolt.org/z/eve54hcx3

@github-actions github-actions bot added the clang Clang issues not falling into any other category label Jan 3, 2025
@EugeneZelenko EugeneZelenko added clang:frontend Language frontend issues, e.g. anything involving "Sema" and removed clang Clang issues not falling into any other category labels Jan 3, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 3, 2025

@llvm/issue-subscribers-clang-frontend

Author: Bo Wang (wangbo15)

Clang rejects the following valid code:
struct B {
  int b[10];
};

struct C
{
  C (B x) {}
};

//OK
//B bb{.b = 42};
//OK
//C c ({.b = {42}});
//OK
//C c({42});
//Fails
C c ({.b = 42});

The question seems to be related to both the designated initializer and the brace elision operation because separately removing the former( like C c({42}); ) or the latter( like C c ({.b = {42}}); ) can both make the code compile.

GCC, MSVC, and EDG always accept it.

The diagnostic of clang:

&lt;source&gt;:17:3: error: no matching constructor for initialization of 'C'
   17 | C c ({.b = 42});
      |   ^  ~~~~~~~~~
&lt;source&gt;:5:8: note: candidate constructor (the implicit copy constructor) not viable: cannot convert initializer list argument to 'const C'
    5 | struct C
      |        ^
&lt;source&gt;:5:8: note: candidate constructor (the implicit move constructor) not viable: cannot convert initializer list argument to 'C'
    5 | struct C
      |        ^
&lt;source&gt;:7:3: note: candidate constructor not viable: cannot convert initializer list argument to 'B'
    7 |   C (B x) {}
      |   ^  ~~~
1 error generated.

https://godbolt.org/z/eve54hcx3

@Endilll
Copy link
Contributor

Endilll commented Jan 4, 2025

It seems that Clang tries to do https://eel.is/c++draft/dcl.init.general#16.9 "Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression" fallback and fails. I can't find anything in [dcl.init] that says how arrays are initialized from a single expression not enclosed in parentheses or braces*. So I believe Clang is correct to reject your example per existing wording.

//OK
//B bb{.b = 42};

You say it's OK, but actually Clang warns that "brace elision for designated initializer is a C99 extension". This might hint to a reason why other compilers accept this.

(*) There is provision https://eel.is/c++draft/dcl.init#string-3 that takes care of string literals that are shorter than a character array they initialize. Clang implements that: https://godbolt.org/z/1hK64zrf1

@EugeneZelenko EugeneZelenko added diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue diverges-from:edg Does the clang frontend diverge from edg compiler labels Jan 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" diverges-from:edg Does the clang frontend diverge from edg compiler diverges-from:gcc Does the clang frontend diverge from gcc on this issue diverges-from:msvc Does the clang frontend diverge from msvc on this issue
Projects
None yet
Development

No branches or pull requests

4 participants