Răsfoiți Sursa

[c++20] Fix crash when constant-evaluating an assignment with a
reference member access on its left-hand side.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373276 91177308-0d34-0410-b5e6-96231b3b80d8

Richard Smith 5 ani în urmă
părinte
comite
66e4895a66
2 a modificat fișierele cu 26 adăugiri și 1 ștergeri
  1. 3 1
      lib/AST/ExprConstant.cpp
  2. 23 0
      test/SemaCXX/constant-expression-cxx2a.cpp

+ 3 - 1
lib/AST/ExprConstant.cpp

@@ -5258,7 +5258,9 @@ static bool HandleUnionActiveMemberChange(EvalInfo &Info, const Expr *LHSExpr,
     //   -- If E is of the form A.B, S(E) contains the elements of S(A)...
     //   -- If E is of the form A.B, S(E) contains the elements of S(A)...
     if (auto *ME = dyn_cast<MemberExpr>(E)) {
     if (auto *ME = dyn_cast<MemberExpr>(E)) {
       auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
       auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
-      if (!FD)
+      // Note that we can't implicitly start the lifetime of a reference,
+      // so we don't need to proceed any further if we reach one.
+      if (!FD || FD->getType()->isReferenceType())
         break;
         break;
 
 
       //    ... and also contains A.B if B names a union member
       //    ... and also contains A.B if B names a union member

+ 23 - 0
test/SemaCXX/constant-expression-cxx2a.cpp

@@ -561,6 +561,29 @@ namespace Union {
     S3 s;
     S3 s;
     s.n = 0;
     s.n = 0;
   }
   }
+
+  union ref_member_1 {
+    int a;
+    int b;
+  };
+  struct ref_member_2 {
+    ref_member_1 &&r;
+  };
+  union ref_member_3 {
+    ref_member_2 a, b;
+  };
+  constexpr int ref_member_test_1() {
+    ref_member_3 r = {.a = {.r = {.a = 1}}};
+    r.a.r.b = 2;
+    return r.a.r.b;
+  }
+  static_assert(ref_member_test_1() == 2);
+  constexpr int ref_member_test_2() { // expected-error {{never produces a constant}}
+    ref_member_3 r = {.a = {.r = {.a = 1}}};
+    // FIXME: This note isn't great. The 'read' here is reading the referent of the reference.
+    r.b.r.b = 2; // expected-note {{read of member 'b' of union with active member 'a'}}
+    return r.b.r.b;
+  }
 }
 }
 
 
 namespace TwosComplementShifts {
 namespace TwosComplementShifts {