diff options
author | Eric Li <li.zhe.hua@gmail.com> | 2024-03-20 12:45:30 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-20 12:45:30 -0400 |
commit | a6a6066290679f23f2bd6b27afc7a06aab07590f (patch) | |
tree | bfbabcb4050a6885eaa92ccc6b6cb158dfd4ed99 /clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | |
parent | 1b5b4eebb6a012cf223954013d34c6e896720822 (diff) | |
download | llvm-a6a6066290679f23f2bd6b27afc7a06aab07590f.zip llvm-a6a6066290679f23f2bd6b27afc7a06aab07590f.tar.gz llvm-a6a6066290679f23f2bd6b27afc7a06aab07590f.tar.bz2 |
[clang][dataflow] Fix crash when analyzing a coroutine (#85957)
A coroutine function body (`CoroutineBodyStmt`) may have null children,
which causes `isa` to segfault.
Diffstat (limited to 'clang/unittests/Analysis/FlowSensitive/TransferTest.cpp')
-rw-r--r-- | clang/unittests/Analysis/FlowSensitive/TransferTest.cpp | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp index a243535..1d3b268 100644 --- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -37,6 +37,40 @@ using ::testing::Ne; using ::testing::NotNull; using ::testing::UnorderedElementsAre; +// Declares a minimal coroutine library. +constexpr llvm::StringRef CoroutineLibrary = R"cc( +struct promise; +struct task; + +namespace std { +template <class, class...> +struct coroutine_traits {}; +template <> +struct coroutine_traits<task> { + using promise_type = promise; +}; + +template <class Promise = void> +struct coroutine_handle { + static constexpr coroutine_handle from_address(void *addr) { return {}; } +}; +} // namespace std + +struct awaitable { + bool await_ready() const noexcept; + void await_suspend(std::coroutine_handle<promise>) const noexcept; + void await_resume() const noexcept; +}; +struct task {}; +struct promise { + task get_return_object(); + awaitable initial_suspend(); + awaitable final_suspend() noexcept; + void unhandled_exception(); + void return_void(); +}; +)cc"; + void runDataflow( llvm::StringRef Code, std::function< @@ -4607,7 +4641,7 @@ TEST(TransferTest, LoopCanProveInvariantForBoolean) { } TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { - std::string Code = R"( + std::string Code = R"cc( union Union { int A; float B; @@ -4618,7 +4652,7 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { Union B; A = B; } - )"; + )cc"; // This is a crash regression test when calling the transfer function on a // `CXXThisExpr` that refers to a union. runDataflow( @@ -4628,6 +4662,22 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) { LangStandard::lang_cxx17, /*ApplyBuiltinTransfer=*/true, "operator="); } +TEST(TransferTest, DoesNotCrashOnNullChildren) { + std::string Code = (CoroutineLibrary + R"cc( + task target() noexcept { + co_return; + } + )cc") + .str(); + // This is a crash regression test when calling `AdornedCFG::build` on a + // statement (in this case, the `CoroutineBodyStmt`) with null children. + runDataflow( + Code, + [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &, + ASTContext &) {}, + LangStandard::lang_cxx20, /*ApplyBuiltinTransfer=*/true); +} + TEST(TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) { std::string Code = R"( struct A { |