aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/AST/Interp/InterpState.cpp70
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;
}