Переглянути джерело

Explorer: fix class destructor not called with `heap.Delete` (#2546)

This change ensures that DestroyAction is executed for the value being deallocated when calling heap.Delete.

Relates to #2521
Adrien Leravat 3 роки тому
батько
коміт
b4e3a3e6cc

+ 12 - 2
explorer/interpreter/interpreter.cpp

@@ -1454,8 +1454,18 @@ auto Interpreter::StepExp() -> ErrorOr<Success> {
         }
         case IntrinsicExpression::Intrinsic::Dealloc: {
           CARBON_CHECK(args.size() == 1);
-          heap_.Deallocate(cast<PointerValue>(args[0])->address());
-          return todo_.FinishAction(TupleValue::Empty());
+          CARBON_CHECK(act.pos() > 0);
+          const auto* ptr = cast<PointerValue>(args[0]);
+          if (act.pos() == 1) {
+            CARBON_ASSIGN_OR_RETURN(
+                const auto* pointee,
+                this->heap_.Read(ptr->address(), exp.source_loc()));
+            return todo_.Spawn(std::make_unique<DestroyAction>(
+                arena_->New<LValue>(ptr->address()), pointee));
+          } else {
+            heap_.Deallocate(ptr->address());
+            return todo_.FinishAction(TupleValue::Empty());
+          }
         }
         case IntrinsicExpression::Intrinsic::Rand: {
           CARBON_CHECK(args.size() == 2);

+ 36 - 0
explorer/testdata/class/new_and_delete.carbon

@@ -0,0 +1,36 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{explorer-run}
+// RUN: %{explorer-run-trace}
+// CHECK:STDOUT: Allocate A
+// CHECK:STDOUT: DESTRUCTOR A
+// CHECK:STDOUT: Delete A
+// CHECK:STDOUT: DESTRUCTOR A
+// CHECK:STDOUT: Return
+// CHECK:STDOUT: result: 0
+
+package ExplorerTest api;
+
+
+class A{
+    fn Create() -> A {
+        return {};
+    }
+    destructor[self: Self] {
+        Print("DESTRUCTOR A");
+    }
+}
+
+fn Main() -> i32 {
+  Print("Allocate A");
+  var pa: A* = heap.New(A.Create());
+
+  Print("Delete A");
+  heap.Delete(pa);
+
+  Print("Return");
+  return 0;
+}

+ 44 - 0
explorer/testdata/class/new_and_delete_hierarchy.carbon

@@ -0,0 +1,44 @@
+// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
+// Exceptions. See /LICENSE for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+// AUTOUPDATE
+// RUN: %{explorer-run}
+// RUN: %{explorer-run-trace}
+// CHECK:STDOUT: Allocate B
+// CHECK:STDOUT: DESTRUCTOR B
+// CHECK:STDOUT: DESTRUCTOR A
+// CHECK:STDOUT: Delete B
+// CHECK:STDOUT: DESTRUCTOR B
+// CHECK:STDOUT: DESTRUCTOR A
+// CHECK:STDOUT: Return
+// CHECK:STDOUT: result: 0
+
+package ExplorerTest api;
+
+
+base class A{
+    destructor[self: Self] {
+        Print("DESTRUCTOR A");
+    }
+}
+
+class B extends A {
+    fn Create() -> Self{
+        return {.base={}};
+    }
+    destructor[self: Self] {
+        Print("DESTRUCTOR B");
+    }
+}
+
+fn Main() -> i32 {
+  Print("Allocate B");
+  var pb: B* = heap.New(B.Create());
+
+  Print("Delete B");
+  heap.Delete(pb);
+
+  Print("Return");
+  return 0;
+}