ChuanqiXu updated this revision to Diff 458353.
ChuanqiXu added a comment.

Address comments.


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

https://reviews.llvm.org/D133341

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/include/clang/Sema/Sema.h
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/CodeGen/CGCoroutine.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp
  clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp
  clang/test/SemaCXX/coroutine-alloc-4.cpp

Index: clang/test/SemaCXX/coroutine-alloc-4.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/coroutine-alloc-4.cpp
@@ -0,0 +1,116 @@
+// Tests that we'll find aligned allocation funciton properly.
+// RUN: %clang_cc1 %s -std=c++20 %s -fsyntax-only -verify -fcoro-aligned-allocation
+
+#include "Inputs/std-coroutine.h"
+
+namespace std {
+    typedef __SIZE_TYPE__ size_t;
+    enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void *operator new(std::size_t); // expected-warning 1+{{found non aligned allocation function for coroutine}}
+  };
+};
+
+task f() {   // expected-error {{'operator new' provided by 'std::coroutine_traits<task>::promise_type' (aka 'task::promise_type') is not usable}}
+    co_return 43;
+}
+
+struct task2 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task2{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void *operator new(std::size_t, std::align_val_t);
+  };
+};
+
+// no diagnostic expected
+task2 f1() {
+    co_return 43;
+}
+
+struct task3 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task3{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void *operator new(std::size_t, std::align_val_t) noexcept;
+    void *operator new(std::size_t) noexcept;
+    static auto get_return_object_on_allocation_failure() { return task3{}; }
+  };
+};
+
+// no diagnostic expected
+task3 f2() {
+    co_return 43;
+}
+
+struct task4 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task4{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void *operator new(std::size_t, std::align_val_t, int, double, int) noexcept;
+  };
+};
+
+// no diagnostic expected
+task4 f3(int, double, int) {
+    co_return 43;
+}
+
+struct task5 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task5{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+  };
+};
+
+// no diagnostic expected.
+// The aligned allocation will be declared by the compiler.
+task5 f4() {
+    co_return 43;
+}
+
+namespace std {
+  struct nothrow_t {};
+  constexpr nothrow_t nothrow = {};
+}
+
+struct task6 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task6{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    static task6 get_return_object_on_allocation_failure() { return task6{}; }
+  };
+};
+
+task6 f5() { // expected-error 1+{{unable to find '::operator new(size_t, align_val_t, nothrow_t)' for 'f5'}}
+    co_return 43;
+}
+
+void *operator new(std::size_t, std::align_val_t, std::nothrow_t) noexcept; 
+
+task6 f6() {
+    co_return 43;
+}
Index: clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCoroutines/coro-aligned-alloc.cpp
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN:   -fcoro-aligned-allocation -S -emit-llvm %s -o - -disable-llvm-passes \
+// RUN:   | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+namespace std {
+    typedef __SIZE_TYPE__ size_t;
+    enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+  };
+};
+
+// CHECK: define{{.*}}@_Z1fv(
+// CHECK: coro.alloc:
+// CHECK: %[[coro_size:.+]] = call{{.*}}@llvm.coro.size
+// CHECK: %[[coro_align:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: %[[aligned_new:.+]] = call{{.*}}@_ZnwmSt11align_val_t({{.*}}%[[coro_size]],{{.*}}%[[coro_align]])
+
+// CHECK: coro.free:
+// CHECK: %[[coro_align_for_free:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: call void @_ZdlPvSt11align_val_t({{.*}}[[coro_align_for_free]]
+
+task f() {
+    co_return 43;
+}
+
+struct task2 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task2{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    static task2 get_return_object_on_allocation_failure() { return task2{}; }
+  };
+};
+
+namespace std {
+  struct nothrow_t {};
+  constexpr nothrow_t nothrow = {};
+}
+
+void *operator new(std::size_t, std::align_val_t, std::nothrow_t) noexcept;
+
+// CHECK: define{{.*}}@_Z2f2v(
+// CHECK: coro.alloc:
+// CHECK: %[[coro_size:.+]] = call{{.*}}@llvm.coro.size
+// CHECK: %[[coro_align:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: %[[aligned_new:.+]] = call{{.*}}@_ZnwmSt11align_val_tSt9nothrow_t({{.*}}%[[coro_size]],{{.*}}%[[coro_align]])
+
+// CHECK: coro.free:
+// CHECK: %[[coro_align_for_free:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: call void @_ZdlPvSt11align_val_t({{.*}}[[coro_align_for_free]]
+
+task2 f2() {
+    co_return 43;
+}
+
+struct task3 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task3{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void operator delete(void *ptr);
+  };
+};
+
+// CHECK: define{{.*}}@_Z2f3v
+// CHECK: coro.free:
+// CHECK: call{{.*}}void @_ZN5task312promise_typedlEPv(
+
+task3 f3() {
+  co_return 43;
+}
+
+struct task4 {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task4{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+    void operator delete(void *ptr, std::align_val_t);
+  };
+};
+
+// CHECK: define{{.*}}@_Z2f4v
+// CHECK: coro.free:
+// CHECK: %[[coro_align_for_free:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: call{{.*}}void @_ZN5task412promise_typedlEPvSt11align_val_t({{.*}}, i64{{.*}}[[coro_align_for_free]]
+
+task4 f4() {
+  co_return 43;
+}
Index: clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCoroutines/coro-aligned-alloc-2.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 \
+// RUN:   -fcoro-aligned-allocation -S -emit-llvm %s -o - -disable-llvm-passes \
+// RUN:   -fsized-deallocation \
+// RUN:   | FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+namespace std {
+    typedef __SIZE_TYPE__ size_t;
+    enum class align_val_t : size_t {};
+}
+
+struct task {
+  struct promise_type {
+    auto initial_suspend() { return std::suspend_always{}; }
+    auto final_suspend() noexcept { return std::suspend_always{}; }
+    auto get_return_object() { return task{}; }
+    void unhandled_exception() {}
+    void return_value(int) {}
+  };
+};
+
+// Test the compiler will chose sized deallocation correctly.
+// This is only enabled with `-fsized-deallocation` which is off by default.
+void operator delete(void *ptr, std::size_t size, std::align_val_t alignment) noexcept;
+
+// CHECK: define{{.*}}@_Z1fv
+// CHECK: coro.free:
+// CHECK: %[[coro_size:.+]] = call{{.*}}@llvm.coro.size
+// CHECK: %[[coro_align:.+]] = call{{.*}}@llvm.coro.align
+// CHECK: call{{.*}}void @_ZdlPvmSt11align_val_t(ptr{{.*}}, i64{{.*}}%[[coro_size]], i64{{.*}}%[[coro_align]])
+
+task f() {
+  co_return 43;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===================================================================
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -3176,7 +3176,8 @@
 
 bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
                                     DeclarationName Name,
-                                    FunctionDecl *&Operator, bool Diagnose) {
+                                    FunctionDecl *&Operator, bool Diagnose,
+                                    bool WantAligned) {
   LookupResult Found(*this, Name, StartLoc, LookupOrdinaryName);
   // Try to find operator delete/operator delete[] in class scope.
   LookupQualifiedName(Found, RD);
@@ -3186,7 +3187,8 @@
 
   Found.suppressDiagnostics();
 
-  bool Overaligned = hasNewExtendedAlignment(*this, Context.getRecordType(RD));
+  bool Overaligned =
+      WantAligned || hasNewExtendedAlignment(*this, Context.getRecordType(RD));
 
   // C++17 [expr.delete]p10:
   //   If the deallocation functions have class scope, the one without a
Index: clang/lib/Sema/SemaCoroutine.cpp
===================================================================
--- clang/lib/Sema/SemaCoroutine.cpp
+++ clang/lib/Sema/SemaCoroutine.cpp
@@ -1030,6 +1030,13 @@
   return DR.get();
 }
 
+static TypeSourceInfo *getTypeSourceInfoForStdAlignValT(Sema &S,
+                                                        SourceLocation Loc) {
+  EnumDecl *StdAlignValT = S.getStdAlignValT();
+  QualType StdAlignValDecl = S.Context.getTypeDeclType(StdAlignValT);
+  return S.Context.getTrivialTypeSourceInfo(StdAlignValDecl);
+}
+
 // Find an appropriate delete for the promise.
 static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType,
                                  FunctionDecl *&OperatorDelete) {
@@ -1039,11 +1046,15 @@
   auto *PointeeRD = PromiseType->getAsCXXRecordDecl();
   assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");
 
+  const bool Overaligned = S.getLangOpts().CoroAlignedAllocation;
+
   // [dcl.fct.def.coroutine]p12
   // 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,
+                                 /*WantAligned*/ Overaligned))
     return false;
 
   // [dcl.fct.def.coroutine]p12
@@ -1056,7 +1067,6 @@
     // Look for a global declaration.
     // Coroutines can always provide their required size.
     const bool CanProvideSize = true;
-    const bool Overaligned = false;
     // Sema::FindUsualDeallocationFunction will try to find the one with two
     // parameters first. It will return the deallocation function with one
     // parameter if failed.
@@ -1323,7 +1333,7 @@
   // lvalue that denotes the parameter copy corresponding to p_i.
 
   FunctionDecl *OperatorNew = nullptr;
-  bool PassAlignment = false;
+  bool PassAlignment = S.getLangOpts().CoroAlignedAllocation;
   SmallVector<Expr *, 1> PlacementArgs;
 
   const bool PromiseContainsNew = [this, &PromiseType]() -> bool {
@@ -1348,6 +1358,7 @@
     if (NewScope == Sema::AFS_Both)
       NewScope = PromiseContainsNew ? Sema::AFS_Class : Sema::AFS_Global;
 
+    PassAlignment = S.getLangOpts().CoroAlignedAllocation;
     FunctionDecl *UnusedResult = nullptr;
     S.FindAllocationFunctions(Loc, SourceRange(), NewScope,
                               /*DeleteScope*/ Sema::AFS_Both, PromiseType,
@@ -1386,11 +1397,23 @@
     LookupAllocationFunction(Sema::AFS_Global);
   }
 
+  // If we found a non-aligned allocation function in the promise_type,
+  // it indicates the user forgot to update the allocation function. Let's emit
+  // a warning here and the error will be emitted in the next.
+  if (PromiseContainsNew && S.getLangOpts().CoroAlignedAllocation &&
+      OperatorNew && !PassAlignment) {
+    S.Diag(OperatorNew->getLocation(),
+           diag::warn_non_aligned_allocation_function)
+        << &FD;
+    OperatorNew = nullptr;
+  }
+
   if (!OperatorNew) {
     if (PromiseContainsNew)
       S.Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;
     else if (RequiresNoThrowAlloc)
-      S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new) << &FD;
+      S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new)
+          << &FD << S.getLangOpts().CoroAlignedAllocation;
 
     return false;
   }
@@ -1421,14 +1444,32 @@
   Expr *FrameSize =
       S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});
 
-  // Make new call.
+  Expr *FrameAlignment = nullptr;
 
+  if (S.getLangOpts().CoroAlignedAllocation) {
+    FrameAlignment =
+        S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_align, {});
+
+    TypeSourceInfo *AlignValTy = getTypeSourceInfoForStdAlignValT(S, Loc);
+    if (!AlignValTy)
+      return false;
+
+    FrameAlignment = S.BuildCXXNamedCast(Loc, tok::kw_static_cast, AlignValTy,
+                                         FrameAlignment, SourceRange(Loc, Loc),
+                                         SourceRange(Loc, Loc))
+                         .get();
+  }
+
+  // Make new call.
   ExprResult NewRef =
       S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);
   if (NewRef.isInvalid())
     return false;
 
   SmallVector<Expr *, 2> NewArgs(1, FrameSize);
+  if (S.getLangOpts().CoroAlignedAllocation)
+    NewArgs.push_back(FrameAlignment);
+
   llvm::append_range(NewArgs, PlacementArgs);
 
   ExprResult NewExpr =
@@ -1458,9 +1499,29 @@
   //   used, the size of the block is passed as the corresponding argument.
   const auto *OpDeleteType =
       OpDeleteQualType.getTypePtr()->castAs<FunctionProtoType>();
-  if (OpDeleteType->getNumParams() > 1)
+  if (OpDeleteType->getNumParams() > DeleteArgs.size() &&
+      S.getASTContext().hasSameType(
+          OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))
     DeleteArgs.push_back(FrameSize);
 
+  // Proposed Change of [dcl.fct.def.coroutine]p12 in P2014R0:
+  //   If deallocation function lookup finds a usual deallocation function with
+  //   a pointer parameter, size parameter and alignment parameter then this
+  //   will be the selected deallocation function, otherwise if lookup finds a
+  //   usual deallocation function with both a pointer parameter and a size
+  //   parameter, then this will be the selected deallocation function.
+  //   Otherwise, if lookup finds a usual deallocation function with only a
+  //   pointer parameter, then this will be the selected deallocation
+  //   function.
+  //
+  // So we are not forced to pass alignment to the deallocation function.
+  if (S.getLangOpts().CoroAlignedAllocation &&
+      OpDeleteType->getNumParams() > DeleteArgs.size() &&
+      S.getASTContext().hasSameType(
+          OpDeleteType->getParamType(DeleteArgs.size()),
+          FrameAlignment->getType()))
+    DeleteArgs.push_back(FrameAlignment);
+
   ExprResult DeleteExpr =
       S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);
   DeleteExpr =
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6416,6 +6416,11 @@
     CmdArgs.push_back("-fcoroutines-ts");
   }
 
+  if (Args.hasFlag(options::OPT_fcoro_aligned_allocation,
+                   options::OPT_fno_coro_aligned_allocation, false) &&
+      types::isCXX(InputType))
+    CmdArgs.push_back("-fcoro-aligned-allocation");
+
   Args.AddLastArg(CmdArgs, options::OPT_fdouble_square_bracket_attributes,
                   options::OPT_fno_double_square_bracket_attributes);
 
Index: clang/lib/CodeGen/CGCoroutine.cpp
===================================================================
--- clang/lib/CodeGen/CGCoroutine.cpp
+++ clang/lib/CodeGen/CGCoroutine.cpp
@@ -683,6 +683,13 @@
     llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_size, T);
     return RValue::get(Builder.CreateCall(F));
   }
+  case llvm::Intrinsic::coro_align: {
+    auto &Context = getContext();
+    CanQualType SizeTy = Context.getSizeType();
+    llvm::IntegerType *T = Builder.getIntNTy(Context.getTypeSize(SizeTy));
+    llvm::Function *F = CGM.getIntrinsic(llvm::Intrinsic::coro_align, T);
+    return RValue::get(Builder.CreateCall(F));
+  }
   // The following three intrinsics take a token parameter referring to a token
   // returned by earlier call to @llvm.coro.id. Since we cannot represent it in
   // builtins, we patch it up here.
Index: clang/lib/CodeGen/CGBuiltin.cpp
===================================================================
--- clang/lib/CodeGen/CGBuiltin.cpp
+++ clang/lib/CodeGen/CGBuiltin.cpp
@@ -4673,6 +4673,8 @@
     return EmitCoroutineIntrinsic(E, Intrinsic::coro_suspend);
   case Builtin::BI__builtin_coro_size:
     return EmitCoroutineIntrinsic(E, Intrinsic::coro_size);
+  case Builtin::BI__builtin_coro_align:
+    return EmitCoroutineIntrinsic(E, Intrinsic::coro_align);
 
   // OpenCL v2.0 s6.13.16.2, Built-in pipe read and write functions
   case Builtin::BIread_pipe:
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6646,8 +6646,8 @@
                                        ArrayRef<QualType> Params);
 
   bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
-                                DeclarationName Name, FunctionDecl* &Operator,
-                                bool Diagnose = true);
+                                DeclarationName Name, FunctionDecl *&Operator,
+                                bool Diagnose = true, bool WantAligned = false);
   FunctionDecl *FindUsualDeallocationFunction(SourceLocation StartLoc,
                                               bool CanProvideSize,
                                               bool Overaligned,
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1186,6 +1186,11 @@
   PosFlag<SetTrue, [CC1Option], "Enable support for the C++ Coroutines TS">,
   NegFlag<SetFalse>>;
 
+defm coro_aligned_allocation : BoolFOption<"coro-aligned-allocation",
+  LangOpts<"CoroAlignedAllocation">, DefaultFalse,
+  PosFlag<SetTrue, [CC1Option], "Prefer aligned allocation for C++ Coroutines">,
+  NegFlag<SetFalse>>;
+
 defm experimental_library : BoolFOption<"experimental-library",
   LangOpts<"ExperimentalLibrary">, DefaultFalse,
   PosFlag<SetTrue, [CC1Option, CoreOption], "Control whether unstable and experimental library features are enabled. "
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -154,6 +154,7 @@
 LANGOPT(NoMathBuiltin     , 1, 0, "disable math builtin functions")
 LANGOPT(GNUAsm            , 1, 1, "GNU-style inline assembly")
 LANGOPT(Coroutines        , 1, 0, "C++20 coroutines")
+LANGOPT(CoroAlignedAllocation, 1, 0, "prefer Aligned Allocation according to P2014's option2")
 LANGOPT(DllExportInlines  , 1, 1, "dllexported classes dllexport inline methods")
 LANGOPT(RelaxedTemplateTemplateArgs, 1, 0, "C++17 relaxed matching of template template arguments")
 LANGOPT(ExperimentalLibrary, 1, 0, "enable unstable and experimental library features")
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11273,7 +11273,14 @@
   "'operator new' provided by %0 is not usable with the function signature of %1"
 >;
 def err_coroutine_unfound_nothrow_new : Error <
-  "unable to find '::operator new(size_t, nothrow_t)' for %0"
+  "unable to find %select{'::operator new(size_t, nothrow_t)'|"
+  "'::operator new(size_t, align_val_t, nothrow_t)'}1 for %0"
+>;
+def warn_non_aligned_allocation_function : Warning <
+  "found non aligned allocation function for coroutine %0">,
+  InGroup<CoroNonAlignedAllocationFunction>;
+def err_conflicting_aligned_options : Error <
+  "conflicting option '-fcoro-aligned-allocation' and '-fno-aligned-allocation'"
 >;
 } // end of coroutines issue category
 
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -66,7 +66,10 @@
   DiagGroup<"deprecated-coroutine", [DeprecatedExperimentalCoroutine]>;
 def AlwaysInlineCoroutine :
   DiagGroup<"always-inline-coroutine">;
-def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedCoroutine, AlwaysInlineCoroutine]>;
+def CoroNonAlignedAllocationFunction :
+  DiagGroup<"coro-non-aligned-allocation-funciton">;
+def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedCoroutine,
+                                        AlwaysInlineCoroutine, CoroNonAlignedAllocationFunction]>;
 def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">;
 def ConstantConversion : DiagGroup<"constant-conversion",
                                    [BitFieldConstantConversion,
Index: clang/include/clang/Basic/Builtins.def
===================================================================
--- clang/include/clang/Basic/Builtins.def
+++ clang/include/clang/Basic/Builtins.def
@@ -1635,6 +1635,7 @@
 LANGBUILTIN(__builtin_coro_promise, "v*v*IiIb", "n", COR_LANG)
 
 LANGBUILTIN(__builtin_coro_size, "z", "n", COR_LANG)
+LANGBUILTIN(__builtin_coro_align, "z", "n", COR_LANG)
 LANGBUILTIN(__builtin_coro_frame, "v*", "n", COR_LANG)
 LANGBUILTIN(__builtin_coro_noop, "v*", "n", COR_LANG)
 LANGBUILTIN(__builtin_coro_free, "v*v*", "n", COR_LANG)
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -149,6 +149,15 @@
 New Compiler Flags
 ------------------
 
+- Implemented `-fcoro-aligned-allocation` flag. This option2 implement
+  option2 for P2014R0 aligned allocation of coroutine frames
+  (`P2014R0 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2014r0.pdf>`_).
+  With this flag, the coroutines will try to lookup aligned allocation
+  function all the time. The compiler will emit an error if it fails to
+  find aligned allocation function. So if the user code implemented self
+  defined allocation function for coroutines, the existing code will be
+  broken.
+
 Deprecated Compiler Flags
 -------------------------
 
Index: clang/docs/ClangCommandLineReference.rst
===================================================================
--- clang/docs/ClangCommandLineReference.rst
+++ clang/docs/ClangCommandLineReference.rst
@@ -1575,6 +1575,11 @@
 
 Enable support for the C++ Coroutines TS
 
+.. option:: -fcoro-aligned-allocation, -fno-coro-aligned-allocation
+
+Enable support for P2014R0 Option2, which will always pursue the aligned allocation function.
+This option is disabled by default.
+
 .. option:: -fcoverage-compilation-dir=<arg>
 
 The compilation directory to embed in the coverage mapping.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to