https://github.com/alinas updated 
https://github.com/llvm/llvm-project/pull/215619

>From ee7976ac94920e64e0212b630bfe00a31eee60b8 Mon Sep 17 00:00:00 2001
From: Alina Sbirlea <[email protected]>
Date: Tue, 11 Aug 2026 05:13:51 +0000
Subject: [PATCH 1/2] [clang] Fix couroutine error for operator new.

Fix error occuring with couroutines:
"error: too many arguments to function call, expected 3, have 4" for operator 
new.

Introduced by cd67cfecb1a1.

AI assisted explanation of the issue:
Prior to cd67cfecb1a1, Sema::FindAllocationFunctions took OperatorNew by 
reference and would unconditionally reset it to nullptr at the beginning of its 
search. The commit changed FindAllocationFunctions to return a 
std::optional<ResolvedAllocation>.

In clang/lib/Sema/SemaCoroutine.cpp, the result is handled like this:

   1     IAP = ImplicitAllocationParameters(
   2         alignedAllocationModeFromBool(ShouldUseAlignedAlloc));
   3
   4     auto FoundAllocations = S.FindAllocationFunctions(...);
   5     if (FoundAllocations) {
   6       IAP = FoundAllocations->IAP;
   7       OperatorNew = FoundAllocations->OperatorNew;
   8     }

  If the coroutine promise defines an unaligned operator new(size_t, void*, 
size_t), the first lookup succeeds but is considered unaligned
  (IAP.PassAlignment resolves to No). Because aligned allocation is enabled by 
default, the coroutine builder attempts a second lookup without placement
  arguments:

   1     if (!OperatorNew || (S.getLangOpts().CoroAlignedAllocation &&
   2                          !isAlignedAllocation(IAP.PassAlignment)))
   3       LookupAllocationFunction(/*NewScope*/ AllocationFunctionScope::Class,
   4                                /*WithoutPlacementArgs*/ true);

  When this second lookup runs, it resets IAP.PassAlignment to Yes at the start 
of the lambda. However, if this second lookup fails to find an aligned
  operator new, FindAllocationFunctions returns std::nullopt.

  Because FoundAllocations is empty, OperatorNew is never reset to nullptr, and 
IAP is never reset to No. They leak state:
   - OperatorNew retains the result from the first successful lookup (which 
takes 3 parameters).
   - IAP.PassAlignment retains the initialized Yes from the second failed 
lookup.
---
 clang/lib/Sema/SemaCoroutine.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index aceb5f2aa33a4..48ee5cc0b0836 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1488,6 +1488,8 @@ bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {
     if (FoundAllocations) {
       IAP = FoundAllocations->IAP;
       OperatorNew = FoundAllocations->OperatorNew;
+    } else {
+      OperatorNew = nullptr;
     }
     assert(!OperatorNew || !OperatorNew->isTypeAwareOperatorNewOrDelete());
   };

>From 92f16920a71bc8c9fee44bb3b8da07c1b8d3360e Mon Sep 17 00:00:00 2001
From: Alina Sbirlea <[email protected]>
Date: Wed, 12 Aug 2026 05:47:53 +0000
Subject: [PATCH 2/2] Add test

---
 clang/test/SemaCXX/coroutine-new-operator.cpp | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 clang/test/SemaCXX/coroutine-new-operator.cpp

diff --git a/clang/test/SemaCXX/coroutine-new-operator.cpp 
b/clang/test/SemaCXX/coroutine-new-operator.cpp
new file mode 100644
index 0000000000000..b28b97fec1eda
--- /dev/null
+++ b/clang/test/SemaCXX/coroutine-new-operator.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -std=c++20 -fcoro-aligned-allocation -fsyntax-only -verify 
%s
+// expected-no-diagnostics
+
+namespace std {
+  template <typename R, typename... Args>
+  struct coroutine_traits {
+    using promise_type = typename R::promise_type;
+  };
+
+  template <class Promise = void> struct coroutine_handle {
+    coroutine_handle() = default;
+    static coroutine_handle from_address(void *) noexcept;
+  };
+  template <> struct coroutine_handle<void> {
+    static coroutine_handle from_address(void *) noexcept;
+    coroutine_handle() = default;
+    template <class Promise>
+    coroutine_handle(coroutine_handle<Promise>) noexcept;
+  };
+
+  struct suspend_always {
+    bool await_ready() const noexcept { return false; }
+    void await_suspend(coroutine_handle<>) const noexcept {}
+    void await_resume() const noexcept {}
+  };
+
+  enum class align_val_t : decltype(sizeof(0)) {};
+} // namespace std
+
+using size_t = decltype(sizeof(0));
+
+struct Task {
+  struct promise_type {
+    std::suspend_always initial_suspend() noexcept { return {}; }
+    std::suspend_always final_suspend() noexcept { return {}; }
+    void return_void() {}
+    void unhandled_exception() {}
+    Task get_return_object() noexcept { return {}; }
+
+    void* operator new(size_t n, void* buf, size_t capacity) noexcept {
+      return buf;
+    }
+    void operator delete(void*) noexcept {}
+  };
+};
+
+Task CoGetReturnAddress(void* buf, size_t capacity) {
+  co_return;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to