Skip to content

Commit a113b4e

Browse files
authored
[clang][Interp] Remove GlobalDecl flag (#101995)
When initializing global variables, we still need to create local variables for temporaries created in the process. Otherwise, we will never call their destructors.
1 parent b4ac7f4 commit a113b4e

File tree

5 files changed

+28
-13
lines changed

5 files changed

+28
-13
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,7 @@ template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
2929
public:
3030
DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
3131
: LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P, VD),
32-
OldGlobalDecl(Ctx->GlobalDecl),
3332
OldInitializingDecl(Ctx->InitializingDecl) {
34-
Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
3533
Ctx->InitializingDecl = VD;
3634
Ctx->InitStack.push_back(InitLink::Decl(VD));
3735
}
@@ -41,14 +39,12 @@ template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
4139
}
4240

4341
~DeclScope() {
44-
this->Ctx->GlobalDecl = OldGlobalDecl;
4542
this->Ctx->InitializingDecl = OldInitializingDecl;
4643
this->Ctx->InitStack.pop_back();
4744
}
4845

4946
private:
5047
Program::DeclScope Scope;
51-
bool OldGlobalDecl;
5248
const ValueDecl *OldInitializingDecl;
5349
};
5450

@@ -2265,7 +2261,7 @@ bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
22652261
// the temporary is explicitly static, create a global variable.
22662262
std::optional<PrimType> SubExprT = classify(SubExpr);
22672263
bool IsStatic = E->getStorageDuration() == SD_Static;
2268-
if (GlobalDecl || IsStatic) {
2264+
if (IsStatic) {
22692265
std::optional<unsigned> GlobalIndex = P.createGlobal(E);
22702266
if (!GlobalIndex)
22712267
return false;

clang/lib/AST/Interp/Compiler.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
389389
llvm::SmallVector<InitLink> InitStack;
390390
bool InitStackActive = false;
391391

392-
/// Flag indicating if we're initializing a global variable.
393-
bool GlobalDecl = false;
394-
395392
/// Type of the expression returned by the function.
396393
std::optional<PrimType> ReturnType;
397394

clang/lib/AST/Interp/Context.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ bool Context::evaluateAsRValue(State &Parent, const Expr *E, APValue &Result) {
5656

5757
if (!Recursing) {
5858
assert(Stk.empty());
59+
C.cleanup();
5960
#ifndef NDEBUG
6061
// Make sure we don't rely on some value being still alive in
6162
// InterpStack memory.
@@ -82,6 +83,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result) {
8283

8384
if (!Recursing) {
8485
assert(Stk.empty());
86+
C.cleanup();
8587
#ifndef NDEBUG
8688
// Make sure we don't rely on some value being still alive in
8789
// InterpStack memory.
@@ -111,6 +113,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
111113

112114
if (!Recursing) {
113115
assert(Stk.empty());
116+
C.cleanup();
114117
#ifndef NDEBUG
115118
// Make sure we don't rely on some value being still alive in
116119
// InterpStack memory.

clang/lib/AST/Interp/Descriptor.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,21 @@ static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
225225

226226
static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst,
227227
const Descriptor *D) {
228-
for (const auto &F : D->ElemRecord->fields()) {
229-
auto FieldOff = F.Offset;
230-
auto *FieldDesc = F.Desc;
228+
assert(D);
229+
assert(D->ElemRecord);
231230

232-
if (auto Fn = FieldDesc->MoveFn)
233-
Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
231+
// FIXME: There might be cases where we need to move over the (v)bases as
232+
// well.
233+
for (const auto &F : D->ElemRecord->fields()) {
234+
auto FieldOffset = F.Offset;
235+
const auto *SrcDesc =
236+
reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;
237+
auto *DestDesc =
238+
reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1;
239+
std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
240+
241+
if (auto Fn = F.Desc->MoveFn)
242+
Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);
234243
}
235244
}
236245

clang/test/AST/Interp/codegen.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,13 @@ namespace reinterpretcast {
5454
// CHECK: define {{.*}} ptr @_ZN15reinterpretcast2f1Em
5555
// CHECK: inttoptr
5656
}
57+
58+
namespace Bitfield {
59+
struct S { int a : 5; ~S(); };
60+
// CHECK: alloca
61+
// CHECK: call {{.*}}memset
62+
// CHECK: store i32 {{.*}}, ptr @_ZGRN8Bitfield1rE_
63+
// CHECK: call void @_ZN8Bitfield1SD1
64+
// CHECK: store ptr @_ZGRN8Bitfield1rE_, ptr @_ZN8Bitfield1rE, align 8
65+
int &&r = S().a;
66+
}

0 commit comments

Comments
 (0)