Skip to content

Commit 660876a

Browse files
[clang] Bail out when handling union access with virtual inheritance
An assertion issue that arose when handling union member access with virtual base class has been addressed. As pointed out by @zygoloid, there is no need for further derived-to-base analysis in this instance, so we can bail out upon encountering a virtual base class. Minor refinement on the function name as we might not be handling a union. Reported-By: ormris Fixes: #65982
1 parent 3d03537 commit 660876a

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6062,8 +6062,9 @@ const AccessKinds StartLifetimeOfUnionMemberHandler::AccessKind;
60626062
/// operator whose left-hand side might involve a union member access. If it
60636063
/// does, implicitly start the lifetime of any accessed union elements per
60646064
/// C++20 [class.union]5.
6065-
static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
6066-
const LValue &LHS) {
6065+
static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
6066+
const Expr *LHSExpr,
6067+
const LValue &LHS) {
60676068
if (LHS.InvalidBase || LHS.Designator.Invalid)
60686069
return false;
60696070

@@ -6118,8 +6119,14 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
61186119
break;
61196120
// Walk path backwards as we walk up from the base to the derived class.
61206121
for (const CXXBaseSpecifier *Elt : llvm::reverse(ICE->path())) {
6122+
if (Elt->isVirtual()) {
6123+
// A class with virtual base classes never has a trivial default
6124+
// constructor, so S(E) is empty in this case.
6125+
E = nullptr;
6126+
break;
6127+
}
6128+
61216129
--PathLength;
6122-
(void)Elt;
61236130
assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(),
61246131
LHS.Designator.Entries[PathLength]
61256132
.getAsBaseOrMember().getPointer()));
@@ -7806,7 +7813,7 @@ class ExprEvaluatorBase
78067813
// per C++20 [class.union]5.
78077814
if (Info.getLangOpts().CPlusPlus20 && OCE &&
78087815
OCE->getOperator() == OO_Equal && MD->isTrivial() &&
7809-
!HandleUnionActiveMemberChange(Info, Args[0], ThisVal))
7816+
!MaybeHandleUnionActiveMemberChange(Info, Args[0], ThisVal))
78107817
return false;
78117818

78127819
Args = Args.slice(1);
@@ -8679,7 +8686,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
86798686
return false;
86808687

86818688
if (Info.getLangOpts().CPlusPlus20 &&
8682-
!HandleUnionActiveMemberChange(Info, E->getLHS(), Result))
8689+
!MaybeHandleUnionActiveMemberChange(Info, E->getLHS(), Result))
86838690
return false;
86848691

86858692
return handleAssignment(this->Info, E, Result, E->getLHS()->getType(),
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify=cxx20 -triple=x86_64-linux-gnu %s
2+
// Fixes assertion triggered by https://github.com/llvm/llvm-project/issues/65982
3+
4+
struct A { int y; };
5+
struct B : virtual public A {};
6+
struct X : public B {};
7+
8+
void member_with_virtual_inheritance() {
9+
X x;
10+
x.B::y = 1;
11+
}

0 commit comments

Comments
 (0)