ChuanqiXu created this revision. ChuanqiXu added reviewers: erichkeane, ychen, rjmccall. ChuanqiXu added projects: clang, clang-language-wg. Herald added a project: All. ChuanqiXu requested review of this revision. Herald added subscribers: cfe-commits, MaskRay.
This implements the option2 of https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2014r0.pdf. This also fixes https://github.com/llvm/llvm-project/issues/56671. Although wg21 didn't get consensus for the direction of the problem, we're happy to have some implementation and user experience first. And from issue56671, the option2 should be the pursued one. Repository: rG LLVM Github Monorepo 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 @@ -6420,6 +6420,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(); + auto SizeTy = Context.getSizeType(); + auto 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 @@ -139,6 +139,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