summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Gesiak <modocache@gmail.com>2019-08-13 12:02:25 +0000
committerBrian Gesiak <modocache@gmail.com>2019-08-13 12:02:25 +0000
commitf8d6836f7a69564193bff27a135f476e1716f5ee (patch)
tree55479faa684caf79df385db5f8d84b4272b61241
parent5065e7817393d9acf2689d3f666a1c375238a7e2 (diff)
downloadbcm5719-llvm-f8d6836f7a69564193bff27a135f476e1716f5ee.tar.gz
bcm5719-llvm-f8d6836f7a69564193bff27a135f476e1716f5ee.zip
[CodeGen] Disable UBSan for coroutine functions
Summary: As explained in http://lists.llvm.org/pipermail/llvm-dev/2018-March/121924.html, the LLVM coroutines transforms are not yet able to move the instructions for UBSan null checking past coroutine suspend boundaries. For now, disable all UBSan checks when generating code for coroutines functions. I also considered an approach where only '-fsanitize=null' would be disabled, However in practice this led to other LLVM errors when writing object files: "Cannot represent a difference across sections". For now, disable all UBSan checks until coroutine transforms are updated to handle them. Test Plan: 1. check-clang 2. Compile the program in https://gist.github.com/modocache/54a036c3bf9c06882fe85122e105d153 using the '-fsanitize=null' option and confirm it does not crash during LLVM IR generation. Reviewers: GorNishanov, vsk, eric_niebler, lewissbaker Reviewed By: vsk Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D44672 llvm-svn: 368675
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp9
-rw-r--r--clang/test/CodeGenCXX/ubsan-coroutines.cpp49
2 files changed, 58 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index f7d9c8201d9..95b8fdce783 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -732,6 +732,15 @@ void CodeGenFunction::StartFunction(GlobalDecl GD,
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>()) {
diff --git a/clang/test/CodeGenCXX/ubsan-coroutines.cpp b/clang/test/CodeGenCXX/ubsan-coroutines.cpp
new file mode 100644
index 00000000000..7dbda6f45a9
--- /dev/null
+++ b/clang/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();
+}
OpenPOWER on IntegriCloud