[c++20] Fix crash when constant-evaluating an assignment with a

reference member access on its left-hand side.

llvm-svn: 373276
This commit is contained in:
Richard Smith 2019-10-01 00:07:14 +00:00
parent f18d747107
commit 9a84dc0b36
2 changed files with 26 additions and 1 deletions

View File

@ -5258,7 +5258,9 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
// -- If E is of the form A.B, S(E) contains the elements of S(A)...
if (auto *ME = dyn_cast<MemberExpr>(E)) {
auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
if (!FD)
// Note that we can't implicitly start the lifetime of a reference,
// so we don't need to proceed any further if we reach one.
if (!FD || FD->getType()->isReferenceType())
break;
// ... and also contains A.B if B names a union member

View File

@ -561,6 +561,29 @@ namespace Union {
S3 s;
s.n = 0;
}
union ref_member_1 {
int a;
int b;
};
struct ref_member_2 {
ref_member_1 &&r;
};
union ref_member_3 {
ref_member_2 a, b;
};
constexpr int ref_member_test_1() {
ref_member_3 r = {.a = {.r = {.a = 1}}};
r.a.r.b = 2;
return r.a.r.b;
}
static_assert(ref_member_test_1() == 2);
constexpr int ref_member_test_2() { // expected-error {{never produces a constant}}
ref_member_3 r = {.a = {.r = {.a = 1}}};
// FIXME: This note isn't great. The 'read' here is reading the referent of the reference.
r.b.r.b = 2; // expected-note {{read of member 'b' of union with active member 'a'}}
return r.b.r.b;
}
}
namespace TwosComplementShifts {