[all-commits] [llvm/llvm-project] 723429: [clang][bytecode] Fix sized builtin operator delet...
cakgok via All-commits
all-commits at lists.llvm.org
Wed May 6 01:03:48 PDT 2026
Branch: refs/heads/main
Home: https://github.com/llvm/llvm-project
Commit: 7234297bf52c0acc4ac0798a50b566fc17041f15
https://github.com/llvm/llvm-project/commit/7234297bf52c0acc4ac0798a50b566fc17041f15
Author: cakgok <cemakgok at gmail.com>
Date: 2026-05-06 (Wed, 06 May 2026)
Changed paths:
M clang/lib/AST/ByteCode/InterpBuiltin.cpp
M clang/test/AST/ByteCode/new-delete.cpp
Log Message:
-----------
[clang][bytecode] Fix sized builtin operator delete handling (#195741)
**Problem:**
A crash happens with std::allocator triggered sized/aligned delete
operations with new constant evaluator.
`interp__builtin_operator_delete` currently consumes the top of the
interpreter stack as a `Pointer`.
This is correct for unsized delete:
```cpp
__builtin_operator_delete(p);
```
but not for sized/aligned delete reached through
`std::allocator<T>::deallocate`:
```cpp
__builtin_operator_delete(p, size);
__builtin_operator_delete(p, size, align);
```
In those cases, the trailing operands are pushed after the pointer, so
the stack top is the size/alignment operand rather than the pointer. The
delete builtin handler must discard those trailing operands first.
Tested versions: 22.1.3, Trunk (x86_64-pc-linux-gnu)
**How to reproduce:**
```cpp
#include <vector>
std::vector<int> v(1);
```
Without any additional headers:
```cpp
typedef __SIZE_TYPE__ size_t;
namespace std {
template <class T>
struct allocator {
constexpr T *allocate(size_t n) {
return static_cast<T *>(__builtin_operator_new(n * sizeof(T)));
}
constexpr void deallocate(T *p, size_t n) {
__builtin_operator_delete(p, n * sizeof(T));
}
};
}
constexpr bool f() {
int *p = std::allocator<int>().allocate(1);
std::allocator<int>().deallocate(p, 1);
return true;
}
static_assert(f());
```
Crashes with:
```bash
clang++ -std=c++20 -fexperimental-new-constant-interpreter test.cpp
```
**Fix:**
Discard all trailing arguments before popping the main pointer argument.
**Testing:**
* Added a regression test.
* The regression goes through `std::allocator<T>::deallocate` rather
than calling `__builtin_operator_delete` directly. Because a direct user
call is caught before the deallocation logic that consumes the pointer
operand.
Assisted-by: gemini-cli
@tbaederr
---------
Co-authored-by: Timm Baeder <tbaeder at redhat.com>
To unsubscribe from these emails, change your notification settings at https://github.com/llvm/llvm-project/settings/notifications
More information about the All-commits
mailing list