[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