diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp | 70 |
1 files changed, 49 insertions, 21 deletions
diff --git a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp index 25684f3c0939..4ea05305540e 100644 --- a/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp +++ b/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp @@ -7,24 +7,17 @@ //===----------------------------------------------------------------------===// #include "InterpState.h" -#include <limits> -#include "Function.h" #include "InterpFrame.h" #include "InterpStack.h" -#include "Opcode.h" -#include "PrimType.h" #include "Program.h" #include "State.h" using namespace clang; using namespace clang::interp; -using APSInt = llvm::APSInt; - InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk, Context &Ctx, SourceMapper *M) - : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr), - CallStackDepth(Parent.getCallStackDepth() + 1) {} + : Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr) {} InterpState::~InterpState() { while (Current) { @@ -35,17 +28,27 @@ InterpState::~InterpState() { while (DeadBlocks) { DeadBlock *Next = DeadBlocks->Next; - free(DeadBlocks); + std::free(DeadBlocks); DeadBlocks = Next; } } +void InterpState::cleanup() { + // As a last resort, make sure all pointers still pointing to a dead block + // don't point to it anymore. + for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) { + for (Pointer *P = DB->B.Pointers; P; P = P->Next) { + P->PointeeStorage.BS.Pointee = nullptr; + } + } + + Alloc.cleanup(); +} + Frame *InterpState::getCurrentFrame() { - if (Current && Current->Caller) { + if (Current && Current->Caller) return Current; - } else { - return Parent.getCurrentFrame(); - } + return Parent.getCurrentFrame(); } bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) { @@ -55,20 +58,45 @@ bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) { } void InterpState::deallocate(Block *B) { - Descriptor *Desc = B->getDescriptor(); + assert(B); + const Descriptor *Desc = B->getDescriptor(); + assert(Desc); + if (B->hasPointers()) { size_t Size = B->getSize(); // Allocate a new block, transferring over pointers. - char *Memory = reinterpret_cast<char *>(malloc(sizeof(DeadBlock) + Size)); + char *Memory = + reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size)); auto *D = new (Memory) DeadBlock(DeadBlocks, B); + std::memset(D->B.rawData(), 0, D->B.getSize()); - // Move data from one block to another. - if (Desc->MoveFn) + // Move data and metadata from the old block to the new (dead)block. + if (B->IsInitialized && Desc->MoveFn) { Desc->MoveFn(B, B->data(), D->data(), Desc); - } else { - // Free storage, if necessary. - if (Desc->DtorFn) - Desc->DtorFn(B, B->data(), Desc); + if (Desc->getMetadataSize() > 0) + std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize()); + } + D->B.IsInitialized = B->IsInitialized; + + // We moved the contents over to the DeadBlock. + B->IsInitialized = false; + } else if (B->IsInitialized) { + B->invokeDtor(); + } +} + +bool InterpState::maybeDiagnoseDanglingAllocations() { + bool NoAllocationsLeft = (Alloc.getNumAllocations() == 0); + + if (!checkingPotentialConstantExpression()) { + for (const auto &It : Alloc.allocation_sites()) { + assert(It.second.size() > 0); + + const Expr *Source = It.first; + CCEDiag(Source->getExprLoc(), diag::note_constexpr_memory_leak) + << (It.second.size() - 1) << Source->getSourceRange(); + } } + return NoAllocationsLeft; } |