Skip to content

Commit

Permalink
[clang][Interp] Propagate InUnion flag to base classes (#102804)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbaederr committed Aug 11, 2024
1 parent bf3aa88 commit fe59b84
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 5 deletions.
11 changes: 6 additions & 5 deletions clang/lib/AST/Interp/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,38 +171,39 @@ 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();
initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField,
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);
}

Expand Down
23 changes: 23 additions & 0 deletions clang/test/AST/Interp/unions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit fe59b84

Please sign in to comment.