]> granicus.if.org Git - clang/commitdiff
Fix hang during constant evaluation of union assignment.
authorEric Fiselier <eric@efcs.ca>
Thu, 23 May 2019 23:34:43 +0000 (23:34 +0000)
committerEric Fiselier <eric@efcs.ca>
Thu, 23 May 2019 23:34:43 +0000 (23:34 +0000)
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

lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression-cxx2a.cpp

index dab40cc5754d615f7d7360156b813e6607efedc7..ac21b63cc79bbc246d2c7787a76311ea0921146f 100644 (file)
@@ -4994,9 +4994,8 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
   llvm::SmallVector<std::pair<unsigned, const FieldDecl*>, 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<MemberExpr>(E)) {
       auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
@@ -5026,6 +5025,7 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
 
     } else if (auto *ICE = dyn_cast<ImplicitCastExpr>(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 {
index a0f92691c27f9f31bea95ca4b0b62397cc295fbe..aa534ce592e34841499f326708002db56a66399c 100644 (file)
@@ -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;
+  }();
 }