Skip to content

Commit ee9bbfa

Browse files
committed
[clang][Interp] Make sure we free() allocated InitMaps
They get allocated when calling initialize() on a primitive array. And they get free'd when the array is fully initialized. However, when that never happens, they get leaked. Fix that by calling the destructor of global variables. Differential Revision: https://reviews.llvm.org/D136826
1 parent 38ffc89 commit ee9bbfa

File tree

5 files changed

+26
-3
lines changed

5 files changed

+26
-3
lines changed

Diff for: clang/lib/AST/Interp/Descriptor.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) {
3939

4040
template <typename T>
4141
static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) {
42+
InitMap *IM = *reinterpret_cast<InitMap **>(Ptr);
43+
if (IM != (InitMap *)-1)
44+
free(IM);
45+
46+
Ptr += sizeof(InitMap *);
4247
for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
4348
reinterpret_cast<T *>(Ptr)[I].~T();
4449
}
@@ -178,7 +183,7 @@ static BlockCtorFn getCtorArrayPrim(PrimType Type) {
178183
}
179184

180185
static BlockDtorFn getDtorArrayPrim(PrimType Type) {
181-
COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr);
186+
TYPE_SWITCH(Type, return dtorArrayTy<T>);
182187
}
183188

184189
static BlockMoveFn getMoveArrayPrim(PrimType Type) {

Diff for: clang/lib/AST/Interp/InterpBlock.h

+6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,12 @@ class Block final {
7373
/*isActive=*/true, Desc);
7474
}
7575

76+
// Invokes the Destructor.
77+
void invokeDtor() {
78+
if (Desc->DtorFn)
79+
Desc->DtorFn(this, data(), Desc);
80+
}
81+
7682
protected:
7783
friend class Pointer;
7884
friend class DeadBlock;

Diff for: clang/lib/AST/Interp/Pointer.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ bool Pointer::isInitialized() const {
143143
Descriptor *Desc = getFieldDesc();
144144
assert(Desc);
145145
if (Desc->isPrimitiveArray()) {
146-
if (Pointee->IsStatic)
146+
if (isStatic() && Base == 0)
147147
return true;
148148
// Primitive array field are stored in a bitset.
149149
InitMap *Map = getInitMap();
@@ -164,7 +164,11 @@ void Pointer::initialize() const {
164164

165165
assert(Desc);
166166
if (Desc->isArray()) {
167-
if (Desc->isPrimitiveArray() && !Pointee->IsStatic) {
167+
if (Desc->isPrimitiveArray()) {
168+
// Primitive global arrays don't have an initmap.
169+
if (isStatic() && Base == 0)
170+
return;
171+
168172
// Primitive array initializer.
169173
InitMap *&Map = getInitMap();
170174
if (Map == (InitMap *)-1)

Diff for: clang/lib/AST/Interp/Program.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ unsigned Program::createGlobalString(const StringLiteral *S) {
6464
unsigned Sz = Desc->getAllocSize();
6565
auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
6666
/*isExtern=*/false);
67+
G->block()->invokeCtor();
6768
Globals.push_back(G);
6869

6970
// Construct the string in storage.

Diff for: clang/lib/AST/Interp/Program.h

+7
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ class Program final {
4747
// here manually so they are properly freeing their resources.
4848
for (auto RecordPair : Records)
4949
RecordPair.second->~Record();
50+
51+
// Manually destroy all the blocks. They are almost all harmless,
52+
// but primitive arrays might have an InitMap* heap allocated and
53+
// that needs to be freed.
54+
for (Global *G : Globals) {
55+
G->block()->invokeDtor();
56+
}
5057
}
5158

5259
/// Marshals a native pointer to an ID for embedding in bytecode.

0 commit comments

Comments
 (0)