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(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()) { 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 struct coroutine_traits { + using promise_type = typename R::promise_type; +}; + +template struct coroutine_handle; +template <> struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; +}; +template struct coroutine_handle : coroutine_handle { + 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(); +}