Skip to content

Commit 01b47eb

Browse files
authored
[clang][bytecode] Only implicitly start lifetime of trivially-default-constructible union members (#149835)
See faee39b
1 parent eb0c863 commit 01b47eb

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,18 @@ using APSInt = llvm::APSInt;
2525
namespace clang {
2626
namespace interp {
2727

28+
static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
29+
assert(FD);
30+
assert(FD->getParent()->isUnion());
31+
const auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());
32+
return !CXXRD || CXXRD->hasTrivialDefaultConstructor();
33+
}
34+
2835
static bool refersToUnion(const Expr *E) {
2936
for (;;) {
3037
if (const auto *ME = dyn_cast<MemberExpr>(E)) {
3138
if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
32-
FD && FD->getParent()->isUnion())
39+
FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))
3340
return true;
3441
E = ME->getBase();
3542
continue;

clang/test/AST/ByteCode/unions.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,61 @@ namespace CopyCtorMutable {
861861
// both-note {{in call}}
862862
}
863863

864+
865+
namespace NonTrivialCtor {
866+
struct A { int x = 1; constexpr int f() { return 1; } };
867+
struct B : A { int y = 1; constexpr int g() { return 2; } };
868+
struct C {
869+
int x;
870+
constexpr virtual int f() = 0;
871+
};
872+
struct D : C {
873+
int y;
874+
constexpr virtual int f() override { return 3; }
875+
};
876+
877+
union U {
878+
int n;
879+
B b;
880+
D d;
881+
};
882+
883+
consteval int test(int which) {
884+
if (which == 0) {}
885+
886+
U u{.n = 5};
887+
assert_active(u);
888+
assert_active(u.n);
889+
assert_inactive(u.b);
890+
891+
switch (which) {
892+
case 0:
893+
u.b.x = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}
894+
return u.b.f();
895+
case 1:
896+
u.b.y = 10; // both-note {{assignment to member 'b' of union with active member 'n'}}
897+
return u.b.g();
898+
case 2:
899+
u.d.x = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}
900+
return u.d.f();
901+
case 3:
902+
u.d.y = 10; // both-note {{assignment to member 'd' of union with active member 'n'}}
903+
return u.d.f();
904+
}
905+
906+
return 1;
907+
}
908+
static_assert(test(0)); // both-error {{not an integral constant expression}} \
909+
// both-note {{in call}}
910+
static_assert(test(1)); // both-error {{not an integral constant expression}} \
911+
// both-note {{in call}}
912+
static_assert(test(2)); // both-error {{not an integral constant expression}} \
913+
// both-note {{in call}}
914+
static_assert(test(3)); // both-error {{not an integral constant expression}} \
915+
// both-note {{in call}}
916+
917+
}
918+
864919
#endif
865920

866921
namespace AddressComparison {

0 commit comments

Comments
 (0)