Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp
35291 views
//===--- InterpState.cpp - Interpreter for the constexpr VM -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "InterpState.h"9#include "InterpFrame.h"10#include "InterpStack.h"11#include "Program.h"12#include "State.h"1314using namespace clang;15using namespace clang::interp;1617InterpState::InterpState(State &Parent, Program &P, InterpStack &Stk,18Context &Ctx, SourceMapper *M)19: Parent(Parent), M(M), P(P), Stk(Stk), Ctx(Ctx), Current(nullptr) {}2021InterpState::~InterpState() {22while (Current) {23InterpFrame *Next = Current->Caller;24delete Current;25Current = Next;26}2728while (DeadBlocks) {29DeadBlock *Next = DeadBlocks->Next;30std::free(DeadBlocks);31DeadBlocks = Next;32}33}3435void InterpState::cleanup() {36// As a last resort, make sure all pointers still pointing to a dead block37// don't point to it anymore.38for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) {39for (Pointer *P = DB->B.Pointers; P; P = P->Next) {40P->PointeeStorage.BS.Pointee = nullptr;41}42}4344Alloc.cleanup();45}4647Frame *InterpState::getCurrentFrame() {48if (Current && Current->Caller)49return Current;50return Parent.getCurrentFrame();51}5253bool InterpState::reportOverflow(const Expr *E, const llvm::APSInt &Value) {54QualType Type = E->getType();55CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;56return noteUndefinedBehavior();57}5859void InterpState::deallocate(Block *B) {60assert(B);61const Descriptor *Desc = B->getDescriptor();62assert(Desc);6364if (B->hasPointers()) {65size_t Size = B->getSize();6667// Allocate a new block, transferring over pointers.68char *Memory =69reinterpret_cast<char *>(std::malloc(sizeof(DeadBlock) + Size));70auto *D = new (Memory) DeadBlock(DeadBlocks, B);71std::memset(D->B.rawData(), 0, D->B.getSize());7273// Move data and metadata from the old block to the new (dead)block.74if (B->IsInitialized && Desc->MoveFn) {75Desc->MoveFn(B, B->data(), D->data(), Desc);76if (Desc->getMetadataSize() > 0)77std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize());78}79D->B.IsInitialized = B->IsInitialized;8081// We moved the contents over to the DeadBlock.82B->IsInitialized = false;83} else if (B->IsInitialized) {84B->invokeDtor();85}86}8788bool InterpState::maybeDiagnoseDanglingAllocations() {89bool NoAllocationsLeft = (Alloc.getNumAllocations() == 0);9091if (!checkingPotentialConstantExpression()) {92for (const auto &It : Alloc.allocation_sites()) {93assert(It.second.size() > 0);9495const Expr *Source = It.first;96CCEDiag(Source->getExprLoc(), diag::note_constexpr_memory_leak)97<< (It.second.size() - 1) << Source->getSourceRange();98}99}100return NoAllocationsLeft;101}102103104