[PATCH] D153962: [clang] Do not discard cleanups while processing immediate invocation

Ilya Biryukov via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 28 10:59:38 PDT 2023


ilya-biryukov added inline comments.


================
Comment at: clang/lib/Sema/SemaExprCXX.cpp:7374
   auto *E = ExprWithCleanups::Create(
       Context, SubExpr, Cleanup.cleanupsHaveSideEffects(), Cleanups);
 
----------------
Because we may potentially pass some cleanups here (which are outside `ConstantExpr`) and won't discard them later, we end up adding the unrelated blocks to this cleanup expression.
Here's an example. If we start with this code:
```cpp
  struct P {
    consteval P() {}
  };

  struct A {
    A(int v) { this->data = new int(v); }
    const int& get() const {
      return *this->data;
    }
    ~A() { delete data; }
  private:
    int *data;
  };

  void foo() {
    A a(1);
  for (; ^{ ptr = &a.get(); }(), P(), false;);
  }
```
And run `clang++ -std=c++20 -fblocks -Xclang=-ast-dump`, we'll get:
(notice same Block in two cleanups)
```
    `-ForStmt 0x5592888b1318 <line:17:3, col:46>
      |-<<<NULL>>>
      |-<<<NULL>>>
      |-ExprWithCleanups 0x5592888b12f0 <col:10, col:39> 'bool'
      | |-cleanup Block 0x5592888ad728
      | `-BinaryOperator 0x5592888b12d0 <col:10, col:39> 'bool' ','
      |   |-BinaryOperator 0x5592888b12a0 <col:10, col:36> 'P':'P' ','
      |   | |-CallExpr 0x5592888adb48 <col:10, col:31> 'void'
      |   | | `-BlockExpr 0x5592888adb30 <col:10, col:29> 'void (^)()'
      |   | |   `-BlockDecl 0x5592888ad728 <col:10, col:29> col:10
      |   | |     |-capture Var 0x5592888ad318 'a' 'A':'A'
      |   | |     `-CompoundStmt 0x5592888ad930 <col:11, col:29>
      |   | `-CXXFunctionalCastExpr 0x5592888b1278 <col:34, col:36> 'P':'P' functional cast to P <NoOp>
      |   |   `-ConstantExpr 0x5592888b1108 <col:34, col:36> 'P':'P'
      |   |     |-value: Struct
      |   |     `-ExprWithCleanups 0x5592888b10e8 <col:34, col:36> 'P':'P'
      |   |       |-cleanup Block 0x5592888ad728
      |   |       `-CXXTemporaryObjectExpr 0x5592888b10b8 <col:34, col:36> 'P':'P' 'void ()'
      |   `-CXXBoolLiteralExpr 0x5592888b12c0 <col:39> 'bool' false
```
I didn't check if this particular error can lead to codegen bug, but even having a misplaced cleanup in the AST is already a red flag.

I think in case of immediate invocations we could simply create `ExprWithCleanups` and not do anything else:
- `CleanupVarDeclMarking` will be handled when containing evaluation context is popped from the stack.
- `ExprCleanupObjects` may only contain blocks at this point (as it's C++ and we have assert for this). One can't use blocks inside a constant expression (Clang will produce an error) so in correct code any cleanups we see inside the current context **must handled by the containing evaluation context** and not this `ExprWithCleanups`.



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D153962/new/

https://reviews.llvm.org/D153962



More information about the cfe-commits mailing list