[clang] faee39b - PR43762: when implicitly changing the active union member for an

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 27 12:31:25 PDT 2019


Author: Richard Smith
Date: 2019-10-27T12:31:16-07:00
New Revision: faee39baa87e43f4b746dd77e479268391163658

URL: https://github.com/llvm/llvm-project/commit/faee39baa87e43f4b746dd77e479268391163658
DIFF: https://github.com/llvm/llvm-project/commit/faee39baa87e43f4b746dd77e479268391163658.diff

LOG: PR43762: when implicitly changing the active union member for an
assignment during constant evaluation, only start the lifetime of
trivially-default-constructible union members.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 42c746e60285..7ed082185670 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -5333,9 +5333,16 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
       if (!FD || FD->getType()->isReferenceType())
         break;
 
-      //    ... and also contains A.B if B names a union member
-      if (FD->getParent()->isUnion())
-        UnionPathLengths.push_back({PathLength - 1, FD});
+      //    ... and also contains A.B if B names a union member ...
+      if (FD->getParent()->isUnion()) {
+        //    ... of a non-class, non-array type, or of a class type with a
+        //    trivial default constructor that is not deleted, or an array of
+        //    such types.
+        auto *RD =
+            FD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
+        if (!RD || RD->hasTrivialDefaultConstructor())
+          UnionPathLengths.push_back({PathLength - 1, FD});
+      }
 
       E = ME->getBase();
       --PathLength;

diff  --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
index 7c1718cebe44..8db705dcdc67 100644
--- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp
@@ -584,6 +584,48 @@ namespace Union {
     r.b.r.b = 2; // expected-note {{read of member 'b' of union with active member 'a'}}
     return r.b.r.b;
   }
+
+  namespace PR43762 {
+    struct A { int x = 1; constexpr int f() { return 1; } };
+    struct B : A { int y = 1; constexpr int g() { return 2; } };
+    struct C {
+      int x;
+      constexpr virtual int f() = 0;
+    };
+    struct D : C {
+      int y;
+      constexpr virtual int f() override { return 3; }
+    };
+
+    union U {
+      int n;
+      B b;
+      D d;
+    };
+
+    constexpr int test(int which) {
+      U u{.n = 5};
+      switch (which) {
+      case 0:
+        u.b.x = 10; // expected-note {{active member 'n'}}
+        return u.b.f();
+      case 1:
+        u.b.y = 10; // expected-note {{active member 'n'}}
+        return u.b.g();
+      case 2:
+        u.d.x = 10; // expected-note {{active member 'n'}}
+        return u.d.f();
+      case 3:
+        u.d.y = 10; // expected-note {{active member 'n'}}
+        return u.d.f();
+      }
+    }
+
+    static_assert(test(0)); // expected-error {{}} expected-note {{in call}}
+    static_assert(test(1)); // expected-error {{}} expected-note {{in call}}
+    static_assert(test(2)); // expected-error {{}} expected-note {{in call}}
+    static_assert(test(3)); // expected-error {{}} expected-note {{in call}}
+  }
 }
 
 namespace TwosComplementShifts {


        


More information about the cfe-commits mailing list