[PATCH] D153294: [clang] Do not create ExprWithCleanups while checking immediate invocation

Mariya Podchishchaeva via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jun 19 09:11:51 PDT 2023


Fznamznon created this revision.
Herald added a project: All.
Fznamznon requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Immediate invocations do not need to run cleanups themselves and the
destructors need to run after each full-expression is processed.
Attempting to add ExprWithCleanups for each immediate invocation may cause
adding it in the wrong place and producing code with memory leaks.

Thanks @ilya-biryukov for helping reducing the reproducer and confirming
that the analysis is correct.

Fixes https://github.com/llvm/llvm-project/issues/60709


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D153294

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenCXX/consteval-cleanup.cpp
  clang/test/SemaCXX/consteval-cleanup.cpp


Index: clang/test/SemaCXX/consteval-cleanup.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/consteval-cleanup.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -Wno-unused-value -std=c++20 -ast-dump -verify %s -ast-dump | FileCheck %s
+
+// expected-no-diagnostics
+
+struct P {
+  consteval P() {}
+};
+
+struct A {
+  A(int v) { this->data = new int(v); }
+  ~A() { delete data; }
+private:
+  int *data;
+};
+
+void foo() {
+  for (;A(1), P(), false;);
+  // CHECK: foo
+  // CHECK: ExprWithCleanups
+  // CHECK-NEXT: BinaryOperator
+  // CHECK: ConstantExpr
+  // CHECK-NOT: ExprWithCleanups
+}
+
+struct B {
+  int *p = new int(38);
+  consteval int get() { return *p; }
+  constexpr ~B() { delete p; }
+};
+
+void bar() {
+  // CHECK: bar
+  // CHECK: ExprWithCleanups
+  // CHECK-NEXT: ConstantExpr
+  int k = B().get();
+}
Index: clang/test/CodeGenCXX/consteval-cleanup.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/consteval-cleanup.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -std=c++20 -Wno-unused-value -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+struct P {
+  consteval P() {}
+};
+
+struct A {
+  A(int v) { this->data = new int(v); }
+  ~A() { delete data; }
+private:
+  int *data;
+};
+
+void foo() {
+  for (;A(1), P(), false;);
+  // CHECK: foo
+  // CHECK: for.cond:
+  // CHECK: call void @_ZN1AC1Ei
+  // CHECK: call void @_ZN1AD1Ev
+  // CHECK: for.body
+}
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -18170,8 +18170,6 @@
     return E;
   }
 
-  E = MaybeCreateExprWithCleanups(E);
-
   ConstantExpr *Res = ConstantExpr::Create(
       getASTContext(), E.get(),
       ConstantExpr::getStorageKind(Decl->getReturnType().getTypePtr(),
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -520,6 +520,10 @@
   type by the default argument promotions, and thus this is UB. Clang's
   behavior now matches GCC's behavior in C++.
   (`#38717 <https://github.com/llvm/llvm-project/issues/38717>_`).
+- Fix missing destructor calls and therefore memory leaks in generated code
+  when an immediate invocation appears as a part of an expression that produces
+  temporaries.
+  (`#60709 <https://github.com/llvm/llvm-project/issues/60709>_`).
 
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D153294.532689.patch
Type: text/x-patch
Size: 2601 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20230619/3319d147/attachment.bin>


More information about the cfe-commits mailing list