[clang] 1c0a90f - [C++20] [Coroutines] Prefer sized deallocation in promise_type

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 14 00:10:12 PDT 2022


Author: Chuanqi Xu
Date: 2022-09-14T15:07:31+08:00
New Revision: 1c0a90fd47bded1a6d5f31091e32cd79434bf4d4

URL: https://github.com/llvm/llvm-project/commit/1c0a90fd47bded1a6d5f31091e32cd79434bf4d4
DIFF: https://github.com/llvm/llvm-project/commit/1c0a90fd47bded1a6d5f31091e32cd79434bf4d4.diff

LOG: [C++20] [Coroutines] Prefer sized deallocation in promise_type

Now when the compiler can't find the sized deallocation function
correctly in promise_type if there are multiple deallocation function
overloads there.

According to [dcl.fct.def.coroutine]p12:
> If both a usual deallocation function with only a pointer parameter
> and a usual deallocation function with both a pointer parameter and a
> size parameter are found, then the selected deallocation function
> shall be the one with two parameters.

So when there are multiple deallocation functions, the compiler should
choose the sized one instead of the unsized one. The patch fixes this.

Added: 
    

Modified: 
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaCoroutine.cpp
    clang/lib/Sema/SemaExprCXX.cpp
    clang/test/CodeGenCoroutines/coro-alloc.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 459c1109b852e..44c4f92592b06 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6646,8 +6646,8 @@ class Sema final {
                                        ArrayRef<QualType> Params);
 
   bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
-                                DeclarationName Name, FunctionDecl* &Operator,
-                                bool Diagnose = true);
+                                DeclarationName Name, FunctionDecl *&Operator,
+                                bool Diagnose = true, bool WantSize = false);
   FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
                                               bool CanProvideSize,
                                               bool Overaligned,

diff  --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
index 31a79e11f21f6..34ed416da3dd6 100644
--- a/clang/lib/Sema/SemaCoroutine.cpp
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -1043,7 +1043,8 @@ static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseTy
   // The deallocation function's name is looked up by searching for it in the
   // scope of the promise type. If nothing is found, a search is performed in
   // the global scope.
-  if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete))
+  if (S.FindDeallocationFunction(Loc, PointeeRD, DeleteName, OperatorDelete,
+                                 /*Diagnose*/ true, /*WantSize*/ true))
     return false;
 
   // [dcl.fct.def.coroutine]p12

diff  --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index bc950ab7c4a7a..1c4e2e968d6c0 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3176,7 +3176,8 @@ FunctionDecl *Sema::FindDeallocationFunctionForDestructor(SourceLocation Loc,
 
 bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
                                     DeclarationName Name,
-                                    FunctionDecl *&Operator, bool Diagnose) {
+                                    FunctionDecl *&Operator, bool Diagnose,
+                                    bool WantSize) {
   LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
   // Try to find operator delete/operator delete[] in class scope.
   LookupQualifiedName(Found, RD);
@@ -3192,7 +3193,7 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
   //   If the deallocation functions have class scope, the one without a
   //   parameter of type std::size_t is selected.
   llvm::SmallVector<UsualDeallocFnInfo, 4> Matches;
-  resolveDeallocationOverload(*this, Found, /*WantSize*/ false,
+  resolveDeallocationOverload(*this, Found, /*WantSize*/ WantSize,
                               /*WantAlign*/ Overaligned, &Matches);
 
   // If we could find an overload, use it.

diff  --git a/clang/test/CodeGenCoroutines/coro-alloc.cpp b/clang/test/CodeGenCoroutines/coro-alloc.cpp
index adcf7a1254f60..c16af68664e72 100644
--- a/clang/test/CodeGenCoroutines/coro-alloc.cpp
+++ b/clang/test/CodeGenCoroutines/coro-alloc.cpp
@@ -243,3 +243,32 @@ extern "C" int f4(promise_on_alloc_failure_tag) {
   // CHECK:   ret i32 %[[LoadRet]]
   co_return;
 }
+
+struct promise_sized_delete_tag2 {};
+
+template <>
+struct std::coroutine_traits<void, promise_sized_delete_tag2> {
+  struct promise_type {
+    // Tests that the compiler can choose the correct operator delete
+    // when we have multiple operator delete
+    void operator delete(void*, unsigned long);
+    void operator delete(void*);
+    void get_return_object() {}
+    suspend_always initial_suspend() { return {}; }
+    suspend_always final_suspend() noexcept { return {}; }
+    void return_void() {}
+  };
+};
+
+// CHECK-LABEL: f5(
+extern "C" void f5(promise_sized_delete_tag2) {
+  // CHECK: %[[ID:.+]] = call token @llvm.coro.id(i32 16
+  // CHECK: %[[SIZE:.+]] = call i64 @llvm.coro.size.i64()
+  // CHECK: call noalias noundef nonnull i8* @_Znwm(i64 noundef %[[SIZE]])
+
+  // CHECK: %[[FRAME:.+]] = call i8* @llvm.coro.begin(
+  // CHECK: %[[MEM:.+]] = call i8* @llvm.coro.free(token %[[ID]], i8* %[[FRAME]])
+  // CHECK: %[[SIZE2:.+]] = call i64 @llvm.coro.size.i64()
+  // CHECK: call void @_ZNSt16coroutine_traitsIJv25promise_sized_delete_tag2EE12promise_typedlEPvm(i8* noundef %[[MEM]], i64 noundef %[[SIZE2]])
+  co_return;
+}


        


More information about the cfe-commits mailing list