diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index 34240ed4352dc6..55182ec383fa15 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -39,6 +39,11 @@ static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) { template static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) { + InitMap *IM = *reinterpret_cast(Ptr); + if (IM != (InitMap *)-1) + free(IM); + + Ptr += sizeof(InitMap *); for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { reinterpret_cast(Ptr)[I].~T(); } @@ -178,7 +183,7 @@ static BlockCtorFn getCtorArrayPrim(PrimType Type) { } static BlockDtorFn getDtorArrayPrim(PrimType Type) { - COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy, return nullptr); + TYPE_SWITCH(Type, return dtorArrayTy); } static BlockMoveFn getMoveArrayPrim(PrimType Type) { diff --git a/clang/lib/AST/Interp/InterpBlock.h b/clang/lib/AST/Interp/InterpBlock.h index e4e693dab09365..9c0b5612b9fae6 100644 --- a/clang/lib/AST/Interp/InterpBlock.h +++ b/clang/lib/AST/Interp/InterpBlock.h @@ -73,6 +73,12 @@ class Block final { /*isActive=*/true, Desc); } + // Invokes the Destructor. + void invokeDtor() { + if (Desc->DtorFn) + Desc->DtorFn(this, data(), Desc); + } + protected: friend class Pointer; friend class DeadBlock; diff --git a/clang/lib/AST/Interp/Pointer.cpp b/clang/lib/AST/Interp/Pointer.cpp index ad4e4e8a8a85b1..c7d9c3a5cd11b2 100644 --- a/clang/lib/AST/Interp/Pointer.cpp +++ b/clang/lib/AST/Interp/Pointer.cpp @@ -143,7 +143,7 @@ bool Pointer::isInitialized() const { Descriptor *Desc = getFieldDesc(); assert(Desc); if (Desc->isPrimitiveArray()) { - if (Pointee->IsStatic) + if (isStatic() && Base == 0) return true; // Primitive array field are stored in a bitset. InitMap *Map = getInitMap(); @@ -164,7 +164,11 @@ void Pointer::initialize() const { assert(Desc); if (Desc->isArray()) { - if (Desc->isPrimitiveArray() && !Pointee->IsStatic) { + if (Desc->isPrimitiveArray()) { + // Primitive global arrays don't have an initmap. + if (isStatic() && Base == 0) + return; + // Primitive array initializer. InitMap *&Map = getInitMap(); if (Map == (InitMap *)-1) diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp index cca59bee1f2013..8ad48976f33d62 100644 --- a/clang/lib/AST/Interp/Program.cpp +++ b/clang/lib/AST/Interp/Program.cpp @@ -64,6 +64,7 @@ unsigned Program::createGlobalString(const StringLiteral *S) { unsigned Sz = Desc->getAllocSize(); auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true, /*isExtern=*/false); + G->block()->invokeCtor(); Globals.push_back(G); // Construct the string in storage. diff --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h index 1a175d8b0f2083..5123dde88c87b7 100644 --- a/clang/lib/AST/Interp/Program.h +++ b/clang/lib/AST/Interp/Program.h @@ -47,6 +47,13 @@ class Program final { // here manually so they are properly freeing their resources. for (auto RecordPair : Records) RecordPair.second->~Record(); + + // Manually destroy all the blocks. They are almost all harmless, + // but primitive arrays might have an InitMap* heap allocated and + // that needs to be freed. + for (Global *G : Globals) { + G->block()->invokeDtor(); + } } /// Marshals a native pointer to an ID for embedding in bytecode.