Skip to content

Commit fe59b84

Browse files
authored
[clang][Interp] Propagate InUnion flag to base classes (#102804)
1 parent bf3aa88 commit fe59b84

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

clang/lib/AST/Interp/Descriptor.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,38 +171,39 @@ static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
171171
unsigned FieldOffset, bool IsVirtualBase) {
172172
assert(D);
173173
assert(D->ElemRecord);
174+
assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
174175

175-
bool IsUnion = D->ElemRecord->isUnion();
176176
auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
177177
Desc->Offset = FieldOffset;
178178
Desc->Desc = D;
179179
Desc->IsInitialized = D->IsArray;
180180
Desc->IsBase = true;
181181
Desc->IsVirtualBase = IsVirtualBase;
182-
Desc->IsActive = IsActive && !IsUnion;
182+
Desc->IsActive = IsActive && !InUnion;
183183
Desc->IsConst = IsConst || D->IsConst;
184184
Desc->IsFieldMutable = IsMutable || D->IsMutable;
185+
Desc->InUnion = InUnion;
185186

186187
for (const auto &V : D->ElemRecord->bases())
187188
initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
188189
V.Desc, V.Offset, false);
189190
for (const auto &F : D->ElemRecord->fields())
190191
initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
191-
IsUnion, F.Desc, F.Offset);
192+
InUnion, F.Desc, F.Offset);
192193
}
193194

194195
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
195196
bool IsActive, bool InUnion, const Descriptor *D) {
196197
for (const auto &V : D->ElemRecord->bases())
197-
initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
198+
initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
198199
false);
199200
for (const auto &F : D->ElemRecord->fields()) {
200201
bool IsUnionField = D->isUnion();
201202
initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField,
202203
InUnion || IsUnionField, F.Desc, F.Offset);
203204
}
204205
for (const auto &V : D->ElemRecord->virtual_bases())
205-
initBase(B, Ptr, IsConst, IsMutable, IsActive, false, V.Desc, V.Offset,
206+
initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
206207
true);
207208
}
208209

clang/test/AST/Interp/unions.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,4 +358,27 @@ namespace CopyCtor {
358358
static_assert(y.b == 42, ""); // both-error {{constant expression}} \
359359
// both-note {{'b' of union with active member 'a'}}
360360
}
361+
362+
namespace UnionInBase {
363+
struct Base {
364+
int y;
365+
};
366+
struct A : Base {
367+
int x;
368+
int arr[3];
369+
union { int p, q; };
370+
};
371+
union B {
372+
A a;
373+
int b;
374+
};
375+
constexpr int read_wrong_member_indirect() { // both-error {{never produces a constant}}
376+
B b = {.b = 1};
377+
int *p = &b.a.y;
378+
return *p; // both-note 2{{read of member 'a' of union with active member 'b'}}
379+
380+
}
381+
static_assert(read_wrong_member_indirect() == 1); // both-error {{not an integral constant expression}} \
382+
// both-note {{in call to}}
383+
}
361384
#endif

0 commit comments

Comments
 (0)