Skip to content

Commit 7ae78be

Browse files
antoniofrighettollvmbot
authored andcommitted
[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: llvm/llvm-project#65982 (cherry picked from commit 660876a4019b81b5a7427a3dcec5ce8c39cd1ee0)
1 parent 4813589 commit 7ae78be

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
@@ -6013,8 +6013,9 @@ const AccessKinds StartLifetimeOfUnionMemberHandler::AccessKind;
60136013
/// operator whose left-hand side might involve a union member access. If it
60146014
/// does, implicitly start the lifetime of any accessed union elements per
60156015
/// C++20 [class.union]5.
6016-
static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
6017-
const LValue &LHS) {
6016+
static bool MaybeHandleUnionActiveMemberChange(EvalInfo &Info,
6017+
const Expr *LHSExpr,
6018+
const LValue &LHS) {
60186019
if (LHS.InvalidBase || LHS.Designator.Invalid)
60196020
return false;
60206021

@@ -6069,8 +6070,14 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
60696070
break;
60706071
// Walk path backwards as we walk up from the base to the derived class.
60716072
for (const CXXBaseSpecifier *Elt : llvm::reverse(ICE->path())) {
6073+
if (Elt->isVirtual()) {
6074+
// A class with virtual base classes never has a trivial default
6075+
// constructor, so S(E) is empty in this case.
6076+
E = nullptr;
6077+
break;
6078+
}
6079+
60726080
--PathLength;
6073-
(void)Elt;
60746081
assert(declaresSameEntity(Elt->getType()->getAsCXXRecordDecl(),
60756082
LHS.Designator.Entries[PathLength]
60766083
.getAsBaseOrMember().getPointer()));
@@ -7748,7 +7755,7 @@ class ExprEvaluatorBase
77487755
// per C++20 [class.union]5.
77497756
if (Info.getLangOpts().CPlusPlus20 && OCE &&
77507757
OCE->getOperator() == OO_Equal && MD->isTrivial() &&
7751-
!HandleUnionActiveMemberChange(Info, Args[0], ThisVal))
7758+
!MaybeHandleUnionActiveMemberChange(Info, Args[0], ThisVal))
77527759
return false;
77537760

77547761
Args = Args.slice(1);
@@ -8621,7 +8628,7 @@ bool LValueExprEvaluator::VisitBinAssign(const BinaryOperator *E) {
86218628
return false;
86228629

86238630
if (Info.getLangOpts().CPlusPlus20 &&
8624-
!HandleUnionActiveMemberChange(Info, E->getLHS(), Result))
8631+
!MaybeHandleUnionActiveMemberChange(Info, E->getLHS(), Result))
86258632
return false;
86268633

86278634
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)