Author: Timm Bäder Date: 2023-03-05T13:18:13+01:00 New Revision: 5e12002c6cea7601073888c2281525131caa77e3
URL: https://github.com/llvm/llvm-project/commit/5e12002c6cea7601073888c2281525131caa77e3 DIFF: https://github.com/llvm/llvm-project/commit/5e12002c6cea7601073888c2281525131caa77e3.diff LOG: Revert "[clang][Interp] Support destructors" This reverts commit 78e4237460bf58f3d6b75f275e0424f38e3b1d04. This breaks the memory sanitizer builder: https://lab.llvm.org/buildbot/#/builders/5/builds/31959 Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/test/AST/Interp/cxx20.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 488d07e09d9b5..bc682c92c143f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -26,10 +26,10 @@ namespace clang { namespace interp { /// Scope used to handle temporaries in toplevel variable declarations. -template <class Emitter> class DeclScope final : public VariableScope<Emitter> { +template <class Emitter> class DeclScope final : public LocalScope<Emitter> { public: DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD) - : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} + : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {} void addExtended(const Scope::Local &Local) override { return this->addLocal(Local); @@ -1857,80 +1857,6 @@ void ByteCodeExprGen<Emitter>::emitCleanup() { C->emitDestruction(); } -/// When calling this, we have a pointer of the local-to-destroy -/// on the stack. -/// Emit destruction of record types (or arrays of record types). -/// FIXME: Handle virtual destructors. -template <class Emitter> -bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) { - assert(Desc); - assert(!Desc->isPrimitive()); - assert(!Desc->isPrimitiveArray()); - - // Arrays. - if (Desc->isArray()) { - const Descriptor *ElemDesc = Desc->ElemDesc; - const Record *ElemRecord = ElemDesc->ElemRecord; - assert(ElemRecord); // This is not a primitive array. - - if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor(); - Dtor && !Dtor->isTrivial()) { - for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) { - if (!this->emitConstUint64(I, SourceInfo{})) - return false; - if (!this->emitArrayElemPtrUint64(SourceInfo{})) - return false; - if (!this->emitRecordDestruction(Desc->ElemDesc)) - return false; - } - } - return this->emitPopPtr(SourceInfo{}); - } - - const Record *R = Desc->ElemRecord; - assert(R); - // First, destroy all fields. - for (const Record::Field &Field : llvm::reverse(R->fields())) { - const Descriptor *D = Field.Desc; - if (!D->isPrimitive() && !D->isPrimitiveArray()) { - if (!this->emitDupPtr(SourceInfo{})) - return false; - if (!this->emitGetPtrField(Field.Offset, SourceInfo{})) - return false; - if (!this->emitRecordDestruction(D)) - return false; - } - } - - // FIXME: Unions need to be handled diff erently here. We don't want to - // call the destructor of its members. - - // Now emit the destructor and recurse into base classes. - if (const CXXDestructorDecl *Dtor = R->getDestructor(); - Dtor && !Dtor->isTrivial()) { - const Function *DtorFunc = getFunction(Dtor); - if (DtorFunc && DtorFunc->isConstexpr()) { - assert(DtorFunc->hasThisPointer()); - assert(DtorFunc->getNumParams() == 1); - if (!this->emitDupPtr(SourceInfo{})) - return false; - if (!this->emitCall(DtorFunc, SourceInfo{})) - return false; - } - } - - for (const Record::Base &Base : llvm::reverse(R->bases())) { - if (!this->emitGetPtrBase(Base.Offset, SourceInfo{})) - return false; - if (!this->emitRecordDestruction(Base.Desc)) - return false; - } - // FIXME: Virtual bases. - - // Remove the instance pointer. - return this->emitPopPtr(SourceInfo{}); -} - namespace clang { namespace interp { diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 4d929278f29c8..231f39ff8bd6d 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -256,8 +256,6 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, return FPO.getRoundingMode(); } - bool emitRecordDestruction(const Descriptor *Desc); - protected: /// Variable to storage mapping. llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; @@ -335,20 +333,9 @@ template <class Emitter> class LocalScope : public VariableScope<Emitter> { this->Ctx->Descriptors[*Idx].emplace_back(Local); } - /// Emit destruction of the local variable. This includes - /// object destructors. void emitDestruction() override { if (!Idx) return; - // Emit destructor calls for local variables of record - // type with a destructor. - for (Scope::Local &Local : this->Ctx->Descriptors[*Idx]) { - if (!Local.Desc->isPrimitive() && !Local.Desc->isPrimitiveArray()) { - this->Ctx->emitGetPtrLocal(Local.Offset, SourceInfo{}); - this->Ctx->emitRecordDestruction(Local.Desc); - } - } - this->Ctx->emitDestroy(*Idx, SourceInfo{}); } diff --git a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp index 547a24e5b19d3..a4be86c0e0639 100644 --- a/clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -428,7 +428,6 @@ bool ByteCodeStmtGen<Emitter>::visitBreakStmt(const BreakStmt *S) { if (!BreakLabel) return false; - this->emitCleanup(); return this->jump(*BreakLabel); } @@ -437,7 +436,6 @@ bool ByteCodeStmtGen<Emitter>::visitContinueStmt(const ContinueStmt *S) { if (!ContinueLabel) return false; - this->emitCleanup(); return this->jump(*ContinueLabel); } diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp index 480d6e8e9a8a2..cc37722730fc2 100644 --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -271,250 +271,3 @@ namespace ConstThis { // ref-error {{must have constant destruction}} \ // ref-note {{in call to}} }; - -namespace Destructors { - - class Inc final { - public: - int &I; - constexpr Inc(int &I) : I(I) {} - constexpr ~Inc() { - I++; - } - }; - - class Dec final { - public: - int &I; - constexpr Dec(int &I) : I(I) {} - constexpr ~Dec() { - I--; - } - }; - - - - constexpr int m() { - int i = 0; - { - Inc f1(i); - Inc f2(i); - Inc f3(i); - } - return i; - } - static_assert(m() == 3, ""); - - - constexpr int C() { - int i = 0; - - while (i < 10) { - Inc inc(i); - continue; - Dec dec(i); - } - return i; - } - static_assert(C() == 10, ""); - - - constexpr int D() { - int i = 0; - - { - Inc i1(i); - { - Inc i2(i); - return i; - } - } - - return i; - } - static_assert(D() == 0, ""); - - constexpr int E() { - int i = 0; - - for(;;) { - Inc i1(i); - break; - } - return i; - } - static_assert(E() == 1, ""); - - - /// FIXME: This should be rejected, since we call the destructor - /// twice. However, GCC doesn't care either. - constexpr int ManualDtor() { - int i = 0; - { - Inc I(i); // ref-note {{destroying object 'I' whose lifetime has already ended}} - I.~Inc(); - } - return i; - } - static_assert(ManualDtor() == 1, ""); // expected-error {{static assertion failed}} \ - // expected-note {{evaluates to '2 == 1'}} \ - // ref-error {{not an integral constant expression}} \ - // ref-note {{in call to 'ManualDtor()'}} - - constexpr void doInc(int &i) { - Inc I(i); - return; - } - constexpr int testInc() { - int i = 0; - doInc(i); - return i; - } - static_assert(testInc() == 1, ""); - constexpr void doInc2(int &i) { - Inc I(i); - // No return statement. - } - constexpr int testInc2() { - int i = 0; - doInc2(i); - return i; - } - static_assert(testInc2() == 1, ""); - - - namespace DtorOrder { - class A { - public: - int &I; - constexpr A(int &I) : I(I) {} - constexpr ~A() { - I = 1337; - } - }; - - class B : public A { - public: - constexpr B(int &I) : A(I) {} - constexpr ~B() { - I = 42; - } - }; - - constexpr int foo() { - int i = 0; - { - B b(i); - } - return i; - } - - static_assert(foo() == 1337); - } - - class FieldDtor1 { - public: - Inc I1; - Inc I2; - constexpr FieldDtor1(int &I) : I1(I), I2(I){} - }; - - constexpr int foo2() { - int i = 0; - { - FieldDtor1 FD1(i); - } - return i; - } - - static_assert(foo2() == 2); - - class FieldDtor2 { - public: - Inc Incs[3]; - constexpr FieldDtor2(int &I) : Incs{Inc(I), Inc(I), Inc(I)} {} - }; - - constexpr int foo3() { - int i = 0; - { - FieldDtor2 FD2(i); - } - return i; - } - - static_assert(foo3() == 3); - - struct ArrD { - int index; - int *arr; - int &p; - constexpr ~ArrD() { - arr[p] = index; - ++p; - } - }; - constexpr bool ArrayOrder() { - int order[3] = {0, 0, 0}; - int p = 0; - { - ArrD ds[3] = { - {1, order, p}, - {2, order, p}, - {3, order, p}, - }; - // ds will be destroyed. - } - return order[0] == 3 && order[1] == 2 && order[2] == 1; - } - static_assert(ArrayOrder()); - - - // Static members aren't destroyed. - class Dec2 { - public: - int A = 0; - constexpr ~Dec2() { - A++; - } - }; - class Foo { - public: - static constexpr Dec2 a; - static Dec2 b; - }; - static_assert(Foo::a.A == 0); - constexpr bool f() { - Foo f; - return true; - } - static_assert(Foo::a.A == 0); - static_assert(f()); - static_assert(Foo::a.A == 0); - - - struct NotConstexpr { - NotConstexpr() {} - ~NotConstexpr() {} - }; - - struct Outer { - constexpr Outer() = default; - constexpr ~Outer(); - - constexpr int foo() { - return 12; - } - - constexpr int bar()const { - return Outer{}.foo(); - } - - static NotConstexpr Val; - }; - - constexpr Outer::~Outer() {} - - constexpr Outer O; - static_assert(O.bar() == 12); -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits