[clang] [clang][Interp] Propagate InUnion flag to base classes (PR #102804)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 11 01:26:45 PDT 2024


https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/102804

None

>From d44bc6ce6fdcd6607b987a74c417e48daf304124 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Sun, 11 Aug 2024 10:25:12 +0200
Subject: [PATCH] [clang][Interp] Propagate InUnion flag to base classes

---
 clang/lib/AST/Interp/Descriptor.cpp | 11 ++++++-----
 clang/test/AST/Interp/unions.cpp    | 23 +++++++++++++++++++++++
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp
index 634413b2f2f52..1b7d9f03f8ef0 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -171,30 +171,31 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
                      unsigned FieldOffset, bool IsVirtualBase) {
   assert(D);
   assert(D->ElemRecord);
+  assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
 
-  bool IsUnion = D->ElemRecord->isUnion();
   auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
   Desc->Offset = FieldOffset;
   Desc->Desc = D;
   Desc->IsInitialized = D->IsArray;
   Desc->IsBase = true;
   Desc->IsVirtualBase = IsVirtualBase;
-  Desc->IsActive = IsActive && !IsUnion;
+  Desc->IsActive = IsActive && !InUnion;
   Desc->IsConst = IsConst || D->IsConst;
   Desc->IsFieldMutable = IsMutable || D->IsMutable;
+  Desc->InUnion = InUnion;
 
   for (const auto &V : D->ElemRecord->bases())
     initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
              V.Desc, V.Offset, false);
   for (const auto &F : D->ElemRecord->fields())
     initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
-              IsUnion, F.Desc, F.Offset);
+              InUnion, F.Desc, F.Offset);
 }
 
 static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
                        bool IsActive, bool InUnion, const Descriptor *D) {
   for (const auto &V : D->ElemRecord->bases())
-    initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
+    initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
              false);
   for (const auto &F : D->ElemRecord->fields()) {
     bool IsUnionField = D->isUnion();
@@ -202,7 +203,7 @@ static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
               InUnion || IsUnionField, F.Desc, F.Offset);
   }
   for (const auto &V : D->ElemRecord->virtual_bases())
-    initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
+    initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
              true);
 }
 
diff --git a/clang/test/AST/Interp/unions.cpp b/clang/test/AST/Interp/unions.cpp
index 4c60c2c0810d4..996d29e143fe2 100644
--- a/clang/test/AST/Interp/unions.cpp
+++ b/clang/test/AST/Interp/unions.cpp
@@ -358,4 +358,27 @@ namespace CopyCtor {
   static_assert(y.b == 42, ""); // both-error {{constant expression}} \
                                 // both-note {{'b' of union with active member 'a'}}
 }
+
+namespace UnionInBase {
+  struct Base {
+    int y;
+  };
+  struct A : Base {
+    int x;
+    int arr[3];
+    union { int p, q; };
+  };
+  union B {
+    A a;
+    int b;
+  };
+  constexpr int read_wrong_member_indirect() { // both-error {{never produces a constant}}
+    B b = {.b = 1};
+    int *p = &b.a.y;
+    return *p; // both-note 2{{read of member 'a' of union with active member 'b'}}
+
+  }
+  static_assert(read_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \
+                                                    // both-note {{in call to}}
+}
 #endif



More information about the cfe-commits mailing list