Index: clang/lib/AST/Interp/Descriptor.cpp =================================================================== --- clang/lib/AST/Interp/Descriptor.cpp +++ clang/lib/AST/Interp/Descriptor.cpp @@ -39,6 +39,11 @@ 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(); } @@ -183,7 +188,7 @@ } static BlockDtorFn getDtorArrayPrim(PrimType Type) { - COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy, return nullptr); + TYPE_SWITCH(Type, return dtorArrayTy); } static BlockMoveFn getMoveArrayPrim(PrimType Type) { Index: clang/lib/AST/Interp/InterpBlock.h =================================================================== --- clang/lib/AST/Interp/InterpBlock.h +++ clang/lib/AST/Interp/InterpBlock.h @@ -100,6 +100,12 @@ /*isActive=*/true, Desc); } + // Invokes the Destructor. + void invokeDtor() { + if (Desc->DtorFn) + Desc->DtorFn(this, data(), Desc); + } + protected: friend class Pointer; friend class DeadBlock; Index: clang/lib/AST/Interp/Pointer.cpp =================================================================== --- clang/lib/AST/Interp/Pointer.cpp +++ clang/lib/AST/Interp/Pointer.cpp @@ -146,7 +146,7 @@ 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(); @@ -167,7 +167,11 @@ 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) Index: clang/lib/AST/Interp/Program.h =================================================================== --- clang/lib/AST/Interp/Program.h +++ clang/lib/AST/Interp/Program.h @@ -47,6 +47,13 @@ // 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. Index: clang/lib/AST/Interp/Program.cpp =================================================================== --- clang/lib/AST/Interp/Program.cpp +++ clang/lib/AST/Interp/Program.cpp @@ -65,6 +65,7 @@ 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.