Index: clang/lib/AST/Interp/EvalEmitter.h =================================================================== --- clang/lib/AST/Interp/EvalEmitter.h +++ clang/lib/AST/Interp/EvalEmitter.h @@ -92,6 +92,8 @@ /// Temporaries which require storage. llvm::DenseMap> Locals; + InlineDescriptor *localInlineDesc(unsigned LocalIndex); + // The emitter always tracks the current instruction and sets OpPC to a token // value which is mapped to the location of the opcode being evaluated. CodePtr OpPC; Index: clang/lib/AST/Interp/EvalEmitter.cpp =================================================================== --- clang/lib/AST/Interp/EvalEmitter.cpp +++ clang/lib/AST/Interp/EvalEmitter.cpp @@ -49,25 +49,33 @@ EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; } +InlineDescriptor *EvalEmitter::localInlineDesc(unsigned LocalIndex) { + auto It = Locals.find(LocalIndex); + assert(It != Locals.end() && "Missing local variable"); + Block *B = reinterpret_cast(It->second.get()); + return reinterpret_cast(B->rawData()); +} + Scope::Local EvalEmitter::createLocal(Descriptor *D) { // Allocate memory for a local. auto Memory = std::make_unique(sizeof(Block) + D->getAllocSize()); auto *B = new (Memory.get()) Block(D, /*isStatic=*/false); B->invokeCtor(); - // Initialize local variable inline descriptor. - InlineDescriptor &Desc = *reinterpret_cast(B->rawData()); - Desc.Desc = D; - Desc.Offset = sizeof(InlineDescriptor); - Desc.IsActive = true; - Desc.IsBase = false; - Desc.IsMutable = false; - Desc.IsConst = false; - Desc.IsInitialized = false; - // Register the local. unsigned Off = Locals.size(); Locals.insert({Off, std::move(Memory)}); + + // Initialize local variable inline descriptor. + InlineDescriptor *Desc = localInlineDesc(Off); + Desc->Desc = D; + Desc->Offset = sizeof(InlineDescriptor); + Desc->IsActive = true; + Desc->IsBase = false; + Desc->IsMutable = false; + Desc->IsConst = false; + Desc->IsInitialized = false; + return {Off, D}; } @@ -240,8 +248,8 @@ assert(It != Locals.end() && "Missing local variable"); auto *B = reinterpret_cast(It->second.get()); *reinterpret_cast(B->data()) = S.Stk.pop(); - InlineDescriptor &Desc = *reinterpret_cast(B->rawData()); - Desc.IsInitialized = true; + InlineDescriptor *Desc = localInlineDesc(I); + Desc->IsInitialized = true; return true; } @@ -254,6 +262,10 @@ auto It = Locals.find(Local.Offset); assert(It != Locals.end() && "Missing local variable"); S.deallocate(reinterpret_cast(It->second.get())); + // Just make sure we're runnnig into some kind of error when a + // local variable is used after being destroyed. + InlineDescriptor *ID = localInlineDesc(I); + std::memset(ID, 0, sizeof(InlineDescriptor)); } return true; Index: clang/lib/AST/Interp/InterpFrame.cpp =================================================================== --- clang/lib/AST/Interp/InterpFrame.cpp +++ clang/lib/AST/Interp/InterpFrame.cpp @@ -75,6 +75,10 @@ void InterpFrame::destroy(unsigned Idx) { for (auto &Local : Func->getScope(Idx).locals()) { S.deallocate(reinterpret_cast(localBlock(Local.Offset))); + // Just make sure we're runnnig into some kind of error when a + // local variable is used after being destroyed. + InlineDescriptor *ID = localInlineDesc(Local.Offset); + std::memset(ID, 0, sizeof(InlineDescriptor)); } }