Open StephanTLavavej opened 4 months ago
@llvm/issue-subscribers-clang-frontend
Author: Stephan T. Lavavej (StephanTLavavej)
Simplified slightly:
struct Handle {
Handle(int) {}
};
union a {
int NoState = 0;
Handle CustomState;
} b;
This is rejected with the following error message:
<source>:7:3: error: call to implicitly-deleted default constructor of 'union a'
7 | } b;
| ^
<source>:6:16: note: default constructor of 'a' is implicitly deleted because field 'CustomState' has no default constructor
6 | Handle CustomState;
| ^
As far as I know an union can only have one active field at a time and since using NSDMI on the field should produce a valid default constructor.
We are hitting this case here:
I believe we need to make a similar change in this case along the lines of the fix in:
https://github.com/llvm/llvm-project/commit/765d8a192180f8f33618087b15c022fe758044af
something like this:
if (SMOR.getKind() == Sema::SpecialMemberOverloadResult::NoMemberOrDeleted) {
if (CSM == Sema::CXXDefaultConstructor && Field && Field->getParent()->isUnion()) {
// [class.default.ctor]p2:
// A defaulted default constructor for class X is defined as deleted if
// - X is a union that has a variant member with a non-trivial default
// constructor and no variant member of X has a default member
// initializer
const auto *RD = cast<CXXRecordDecl>(Field->getParent());
if (!RD->hasInClassInitializer())
DiagKind = !Decl ? 0 : 1;
}else {
DiagKind = !Decl ? 0 : 1;
}
}
This passes check-clang
with a minor diagnostic fix in a test.
CC @royjacobson @AaronBallman @cor3ntin
That seems roughly correct to me, good catch @shafik!
Accepted by VS 2022 17.10 Preview 1, rejected by Clang 17.0.3.
On Compiler Explorer, accepted by GCC 13.2, rejected by Clang 17.0.1 and trunk: https://godbolt.org/z/8fGhWa1ss
Presumably related to #48416 which was previously reported and fixed, but this larger repro is still failing.