@@ -37,6 +37,40 @@ using ::testing::Ne;
3737using ::testing::NotNull;
3838using ::testing::UnorderedElementsAre;
3939
40+ // Declares a minimal coroutine library.
41+ constexpr llvm::StringRef CoroutineLibrary = R"cc(
42+ struct promise;
43+ struct task;
44+
45+ namespace std {
46+ template <class, class...>
47+ struct coroutine_traits {};
48+ template <>
49+ struct coroutine_traits<task> {
50+ using promise_type = promise;
51+ };
52+
53+ template <class Promise = void>
54+ struct coroutine_handle {
55+ static constexpr coroutine_handle from_address(void *addr) { return {}; }
56+ };
57+ } // namespace std
58+
59+ struct awaitable {
60+ bool await_ready() const noexcept;
61+ void await_suspend(std::coroutine_handle<promise>) const noexcept;
62+ void await_resume() const noexcept;
63+ };
64+ struct task {};
65+ struct promise {
66+ task get_return_object();
67+ awaitable initial_suspend();
68+ awaitable final_suspend() noexcept;
69+ void unhandled_exception();
70+ void return_void();
71+ };
72+ )cc" ;
73+
4074void runDataflow (
4175 llvm::StringRef Code,
4276 std::function<
@@ -4607,7 +4641,7 @@ TEST(TransferTest, LoopCanProveInvariantForBoolean) {
46074641}
46084642
46094643TEST (TransferTest, DoesNotCrashOnUnionThisExpr) {
4610- std::string Code = R"(
4644+ std::string Code = R"cc (
46114645 union Union {
46124646 int A;
46134647 float B;
@@ -4618,7 +4652,7 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
46184652 Union B;
46194653 A = B;
46204654 }
4621- )" ;
4655+ )cc " ;
46224656 // This is a crash regression test when calling the transfer function on a
46234657 // `CXXThisExpr` that refers to a union.
46244658 runDataflow (
@@ -4628,6 +4662,22 @@ TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
46284662 LangStandard::lang_cxx17, /* ApplyBuiltinTransfer=*/ true , " operator=" );
46294663}
46304664
4665+ TEST (TransferTest, DoesNotCrashOnNullChildren) {
4666+ std::string Code = (CoroutineLibrary + R"cc(
4667+ task target() noexcept {
4668+ co_return;
4669+ }
4670+ )cc" )
4671+ .str ();
4672+ // This is a crash regression test when calling `AdornedCFG::build` on a
4673+ // statement (in this case, the `CoroutineBodyStmt`) with null children.
4674+ runDataflow (
4675+ Code,
4676+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &,
4677+ ASTContext &) {},
4678+ LangStandard::lang_cxx20, /* ApplyBuiltinTransfer=*/ true );
4679+ }
4680+
46314681TEST (TransferTest, StructuredBindingAssignFromStructIntMembersToRefs) {
46324682 std::string Code = R"(
46334683 struct A {
0 commit comments