This revision was automatically updated to reflect the committed changes. Closed by commit rL368675: [CodeGen] Disable UBSan for coroutine functions (authored by modocache, committed by ). Herald added a project: LLVM. Herald added a subscriber: llvm-commits.
Changed prior to commit: https://reviews.llvm.org/D44672?vs=214370&id=214809#toc Repository: rL LLVM CHANGES SINCE LAST ACTION https://reviews.llvm.org/D44672/new/ https://reviews.llvm.org/D44672 Files: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp Index: cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp @@ -0,0 +1,49 @@ +// This test merely verifies that emitting the object file does not cause a +// crash when the LLVM coroutines passes are run. +// RUN: %clang_cc1 -emit-obj -std=c++2a -fsanitize=null %s -o %t.o + +namespace std::experimental { +template <typename R, typename... T> struct coroutine_traits { + using promise_type = typename R::promise_type; +}; + +template <class Promise = void> struct coroutine_handle; +template <> struct coroutine_handle<void> { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template <class PromiseType> + coroutine_handle(coroutine_handle<PromiseType>) noexcept; +}; +template <class Promise> struct coroutine_handle : coroutine_handle<void> { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; +} + +struct suspend_always { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct task { + struct promise_type { + task get_return_object() { return task(); } + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception() {} + }; +}; + +struct awaitable { + task await() { (void)co_await *this; } + bool await_ready() { return false; } + bool await_suspend(std::experimental::coroutine_handle<> awaiter) { return false; } + bool await_resume() { return false; } +}; + +int main() { + awaitable a; + a.await(); +} Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -732,6 +732,15 @@ SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast; } + // Ignore null checks in coroutine functions since the coroutines passes + // are not aware of how to move the extra UBSan instructions across the split + // coroutine boundaries. + if (D && SanOpts.has(SanitizerKind::Null)) + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->getBody() && + FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass) + SanOpts.Mask &= ~SanitizerKind::Null; + // Apply xray attributes to the function (as a string, for now) if (D) { if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
Index: cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-coroutines.cpp @@ -0,0 +1,49 @@ +// This test merely verifies that emitting the object file does not cause a +// crash when the LLVM coroutines passes are run. +// RUN: %clang_cc1 -emit-obj -std=c++2a -fsanitize=null %s -o %t.o + +namespace std::experimental { +template <typename R, typename... T> struct coroutine_traits { + using promise_type = typename R::promise_type; +}; + +template <class Promise = void> struct coroutine_handle; +template <> struct coroutine_handle<void> { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template <class PromiseType> + coroutine_handle(coroutine_handle<PromiseType>) noexcept; +}; +template <class Promise> struct coroutine_handle : coroutine_handle<void> { + coroutine_handle() = default; + static coroutine_handle from_address(void *) noexcept; +}; +} + +struct suspend_always { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<>) noexcept; + void await_resume() noexcept; +}; + +struct task { + struct promise_type { + task get_return_object() { return task(); } + suspend_always initial_suspend() { return {}; } + suspend_always final_suspend() { return {}; } + void return_void() {} + void unhandled_exception() {} + }; +}; + +struct awaitable { + task await() { (void)co_await *this; } + bool await_ready() { return false; } + bool await_suspend(std::experimental::coroutine_handle<> awaiter) { return false; } + bool await_resume() { return false; } +}; + +int main() { + awaitable a; + a.await(); +} Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -732,6 +732,15 @@ SanOpts.Mask &= ~SanitizerKind::CFIUnrelatedCast; } + // Ignore null checks in coroutine functions since the coroutines passes + // are not aware of how to move the extra UBSan instructions across the split + // coroutine boundaries. + if (D && SanOpts.has(SanitizerKind::Null)) + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + if (FD->getBody() && + FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass) + SanOpts.Mask &= ~SanitizerKind::Null; + // Apply xray attributes to the function (as a string, for now) if (D) { if (const auto *XRayAttr = D->getAttr<XRayInstrumentAttr>()) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits