-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[Clang] Partial implementation of support for P3074 (trivial unions) #146815
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
base: main
Are you sure you want to change the base?
Changes from all commits
40290a9
59b0649
e7cc4ec
5eb68c5
80e2476
9972d7e
c2f3a05
1283ddb
eed0988
64babbc
23bf694
8aebb45
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| // RUN: %clang_cc1 -verify -std=c++26 %s -Wno-defaulted-function-deleted -triple x86_64-linux-gnu | ||
|
|
||
| struct NonTrivial { | ||
brevzin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| int i; | ||
| constexpr NonTrivial(int i) :i(i) { } | ||
| constexpr ~NonTrivial() { } | ||
| }; | ||
|
|
||
| union U0 { | ||
| NonTrivial nt; | ||
| int i; | ||
| }; | ||
| U0 u0; | ||
|
|
||
| // check for constant evaluation failure | ||
| constexpr NonTrivial make() { | ||
| U0 u0; | ||
| return u0.nt; | ||
| } | ||
| constexpr NonTrivial nt = make(); // expected-error {{must be initialized by a constant expression}}} | ||
| // expected-note@-3 {{union with no active member}} | ||
| // expected-note@-4 {{in call to 'NonTrivial(u0.nt)'}} | ||
| // expected-note@-3 {{in call to 'make()'}} | ||
|
|
||
| // overload resolution to select a constructor to default-initialize an object of type X either fails | ||
| union U1 { | ||
| U1(int); | ||
| NonTrivial nt; // #1 | ||
| }; | ||
| U1 u1(1); // expected-error {{deleted function}} expected-note@#1 {{non-trivial destructor}} | ||
|
|
||
| // or selects a constructor that is either deleted or not trivial, or | ||
| union U2 { | ||
| U2() : nt(2) { } | ||
| NonTrivial nt; // #2 | ||
| }; | ||
| U2 u2; // expected-error {{deleted function}} expected-note@#2 {{non-trivial destructor}} | ||
|
|
||
| union U3 { | ||
| U3() = delete; | ||
| U3(int); | ||
| NonTrivial nt; // #3 | ||
| }; | ||
| U3 u3(1); // expected-error {{deleted function}} expected-note@#3 {{non-trivial destructor}} | ||
|
|
||
| // or X has a variant member V of class type M (or possibly multi-dimensional array thereof) where V has a default member initializer and M has a destructor that is non-trivial, | ||
brevzin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| union U4 { | ||
| NonTrivial nt = 1; // #4 | ||
| }; | ||
| U4 u4; // expected-error {{deleted function}} expected-note@#4 {{non-trivial destructor}} | ||
|
|
||
| union U5 { | ||
| NonTrivial nt[2] = {1, 2}; // #5 | ||
| }; | ||
| U5 u5; // expected-error {{deleted function}} expected-note@#5 {{non-trivial destructor}} | ||
|
|
||
| union U6 { | ||
| NonTrivial nt; | ||
| U6* next = nullptr; | ||
| }; | ||
| U6 u6; | ||
|
|
||
| union U7 { | ||
| U7() = default; | ||
| NonTrivial nt; | ||
| U6* next = nullptr; | ||
| }; | ||
| U7 u7; | ||
|
|
||
| union U8 { | ||
| struct { | ||
| NonTrivial x; | ||
| }; | ||
| } u8; | ||
|
|
||
| union U9 { | ||
| struct { | ||
| NonTrivial x = 1; // #6 | ||
| }; | ||
| } u9; // expected-error {{deleted function}} | ||
|
|
||
| struct DeletedDtor { | ||
| ~DeletedDtor() = delete; // expected-note 2 {{deleted here}} | ||
| }; | ||
| union B1 { | ||
| B1(); | ||
| DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} | ||
| }; | ||
| B1 b1; // expected-error {{deleted function}} | ||
| union B2 { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some more cases: union A {
struct {
NonTrivial x; // W/ and w/o a default member initialiser.
};
};
A a;
struct B {
union {
NonTrivial x; // as above
};
};
B b;
union {
struct {
union {
struct {
union {
NonTrivial x; // as above
};
};
};
};
} c;
struct {
union {
struct {
union {
struct {
NonTrivial x; // as above
};
};
};
};
} d;
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alright I'm not handling this case correctly, but I can't figure out why: union U9 {
struct {
NonTrivial x = 1; // #6
};
} u9; // expected-error {{deleted function}}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, at a glance nothing jumps out to me; we do create a I did spot a fixme about anonymous unions inside anonymous unions, so er, here’s another gross test case I suppose: union {
union {
NonTrivial x;
};
} a; |
||
| B2(); | ||
| union { // expected-note {{deleted destructor}} | ||
| DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}} | ||
| }; | ||
| }; | ||
| B2 b2; // expected-error {{deleted function}} | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That ‘is missing exception specification 'noexcept'’ error is weird; I’m also getting that before C++26 and only Clang errors on this; GCC, MSVC, and EDG seem to be fine with it. I don’t think that has anything to do w/ this patch but it’s still strange.