From: Eric Fiselier Date: Thu, 23 May 2019 23:34:43 +0000 (+0000) Subject: Fix hang during constant evaluation of union assignment. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a3332061d757fadd75dbd2402d7e23d6cf6f901e;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@361571 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index dab40cc575..ac21b63cc7 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -4994,9 +4994,8 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, llvm::SmallVector, 4> UnionPathLengths; // C++ [class.union]p5: // define the set S(E) of subexpressions of E as follows: - const Expr *E = LHSExpr; unsigned PathLength = LHS.Designator.Entries.size(); - while (E) { + for (const Expr *E = LHSExpr; E != nullptr;) { // -- If E is of the form A.B, S(E) contains the elements of S(A)... if (auto *ME = dyn_cast(E)) { auto *FD = dyn_cast(ME->getMemberDecl()); @@ -5026,6 +5025,7 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, } else if (auto *ICE = dyn_cast(E)) { // Step over a derived-to-base conversion. + E = ICE->getSubExpr(); if (ICE->getCastKind() == CK_NoOp) continue; if (ICE->getCastKind() != CK_DerivedToBase && @@ -5038,7 +5038,6 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr, LHS.Designator.Entries[PathLength] .getAsBaseOrMember().getPointer())); } - E = ICE->getSubExpr(); // -- Otherwise, S(E) is empty. } else { diff --git a/test/SemaCXX/constant-expression-cxx2a.cpp b/test/SemaCXX/constant-expression-cxx2a.cpp index a0f92691c2..aa534ce592 100644 --- a/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/test/SemaCXX/constant-expression-cxx2a.cpp @@ -513,4 +513,12 @@ namespace Union { static_assert(return_init_all().a.p == 7); // expected-error {{}} expected-note {{read of member 'p' of union with no active member}} static_assert(return_init_all().a.q == 8); // expected-error {{}} expected-note {{read of member 'q' of union with no active member}} constexpr B init_all = return_init_all(); + + constexpr bool test_no_member_change = []{ + union U { char dummy = {}; }; + U u1; + U u2; + u1 = u2; + return true; + }(); }