Skip to content

Commit ffafdb9

Browse files
committed
Fix hang during constant evaluation of union assignment.
HandleUnionActiveMemberChange forgot to walk over a nop implicit conversion node and got stuck in the process. As a cleanup I changed the declaration of `E` so it can't be accidentally accessed after the loop. llvm-svn: 361571
1 parent 093c922 commit ffafdb9

File tree

2 files changed

+10
-3
lines changed

2 files changed

+10
-3
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4994,9 +4994,8 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
49944994
llvm::SmallVector<std::pair<unsigned, const FieldDecl*>, 4> UnionPathLengths;
49954995
// C++ [class.union]p5:
49964996
// define the set S(E) of subexpressions of E as follows:
4997-
const Expr *E = LHSExpr;
49984997
unsigned PathLength = LHS.Designator.Entries.size();
4999-
while (E) {
4998+
for (const Expr *E = LHSExpr; E != nullptr;) {
50004999
// -- If E is of the form A.B, S(E) contains the elements of S(A)...
50015000
if (auto *ME = dyn_cast<MemberExpr>(E)) {
50025001
auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
@@ -5026,6 +5025,7 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
50265025

50275026
} else if (auto *ICE = dyn_cast<ImplicitCastExpr>(E)) {
50285027
// Step over a derived-to-base conversion.
5028+
E = ICE->getSubExpr();
50295029
if (ICE->getCastKind() == CK_NoOp)
50305030
continue;
50315031
if (ICE->getCastKind() != CK_DerivedToBase &&
@@ -5038,7 +5038,6 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
50385038
LHS.Designator.Entries[PathLength]
50395039
.getAsBaseOrMember().getPointer()));
50405040
}
5041-
E = ICE->getSubExpr();
50425041

50435042
// -- Otherwise, S(E) is empty.
50445043
} else {

clang/test/SemaCXX/constant-expression-cxx2a.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,4 +513,12 @@ namespace Union {
513513
static_assert(return_init_all().a.p == 7); // expected-error {{}} expected-note {{read of member 'p' of union with no active member}}
514514
static_assert(return_init_all().a.q == 8); // expected-error {{}} expected-note {{read of member 'q' of union with no active member}}
515515
constexpr B init_all = return_init_all();
516+
517+
constexpr bool test_no_member_change = []{
518+
union U { char dummy = {}; };
519+
U u1;
520+
U u2;
521+
u1 = u2;
522+
return true;
523+
}();
516524
}

0 commit comments

Comments
 (0)