[llvm-bugs] [Bug 48626] New: clang crashes with "Call referring to the coroutine frame cannot be marked as musttail"

via llvm-bugs llvm-bugs at lists.llvm.org
Tue Dec 29 17:08:33 PST 2020


https://bugs.llvm.org/show_bug.cgi?id=48626

            Bug ID: 48626
           Summary: clang crashes with "Call referring to the coroutine
                    frame cannot be marked as musttail"
           Product: libraries
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: Transformation Utilities
          Assignee: unassignedbugs at nondot.org
          Reporter: cygnus at michiru.ru
                CC: gornishanov at gmail.com, llvm-bugs at lists.llvm.org

Created attachment 24320
  --> https://bugs.llvm.org/attachment.cgi?id=24320&action=edit
Original non-minified reproducer

(There's no component for bugs in lib/Transforms/Coroutines and I see no system
in how other bugs with a "coroutine" in title are reported that are not clang
frontend-specific, which could be reported as product:clang/component:c++2a;
please adjust as needed.)

llvm/lib/Transforms/Coroutines/CoroElide.cpp:87 in removeTailCallAttribute
called from Lowerer::elideHeapAllocations says:

// FIXME: If we ever hit this check. Evaluate whether it is more
// appropriate to retain musttail and allow the code to compile.

Well, this happened for me. Here's the result from reducing original
preprocessed code with cvise and manually editing it to make some sense, some
functions happen to be undefined here as that matters for the bug to manifest,
this wasn't the case in the original code that I have left attached in case it
would help.

$ cat bug.cpp

#include <experimental/coroutine>

namespace stdcoro = std::experimental;

template<bool SaveAwaiter,typename Result>
struct coroutine
{
    struct promise_type
    {
        struct final_awaitable : stdcoro::suspend_always
        {
            stdcoro::coroutine_handle<>
await_suspend(stdcoro::coroutine_handle<>) noexcept;
        };

        Result result_;

        coroutine<SaveAwaiter,Result> get_return_object() noexcept
        {
            return *this;
        }

        stdcoro::suspend_always initial_suspend() noexcept
        {
            return {};
        }

        auto final_suspend() noexcept
        {
            if constexpr(SaveAwaiter)
                return final_awaitable{};
            else
                return stdcoro::suspend_always{};
        }

        void unhandled_exception()
        {
            __builtin_unreachable();
        }

        void return_value(int result)
        {
            result_ = result;
        }

        Result result()
        {
            return result_;
        }
    };

    using handle_t = stdcoro::coroutine_handle<promise_type>;
    using result_type = Result;

    handle_t handle_;

    ~coroutine()
    {
        handle_.destroy();
    }

    auto operator()() noexcept
    {
        struct coroutine_result
        {
            coroutine *coro_;

            coroutine_result(coroutine *coro)
                : coro_{coro}
            {
                coro_->handle_();
            }

            operator result_type()
            {
                return coro_->handle_.promise().result();
            }
        };
        return coroutine_result{this};
    }

    coroutine(promise_type& promise)
        :
handle_{stdcoro::coroutine_handle<promise_type>::from_promise(promise)}
    {}
};

template<typename T> void report(T);
extern template void report<int>(int);

template<typename T>
void expect(T assertion)
{
    if(!assertion)
        report(assertion);
}

int main()
{
    []() -> coroutine<true,int> {
        expect([]() -> coroutine<false,int> { co_return 1; }()());
        co_return 0;
    }();
}

$ lldb -- clang++ -O2 -std=c++20 -c bug.cpp
(lldb) target create "clang++"
Current executable set to 'clang++' (x86_64).
(lldb) settings set -- target.run-args  "-O2" "-std=c++20" "-c" "bug.cpp"
(lldb) b LLVMErrorHandler
Breakpoint 1: 2 locations.
(lldb) r
Process 807971 launched: '/usr/lib/llvm/12/bin/clang++' (x86_64)
Process 807971 stopped
* thread #1, name = 'clang++', stop reason = breakpoint 1.1
    frame #0: 0x000000000022b604
clang++`LLVMErrorHandler(UserData=0x00000000002925e0, Message="Call referring
to the coroutine frame cannot be marked as musttail", GenCrashDiag=true) at
cc1_main.cpp:64:9
   61                                bool GenCrashDiag) {
   62     DiagnosticsEngine &Diags =
*static_cast<DiagnosticsEngine*>(UserData);
   63
-> 64     Diags.Report(diag::err_fe_error_backend) << Message;
   65
   66     // Run the interrupt handlers to make sure any special cleanups get
done, in
   67     // particular that we remove files registered with
RemoveFileOnSignal.
(lldb) bt
* thread #1, name = 'clang++', stop reason = breakpoint 1.1
  * frame #0: 0x000000000022b604
clang++`LLVMErrorHandler(UserData=0x00000000002925e0, Message="Call referring
to the coroutine frame cannot be marked as musttail", GenCrashDiag=true) at
cc1_main.cpp:64:9
    frame #1: 0x00007ffff1a46e60
libLLVM-12libcxx.so`llvm::report_fatal_error(Reason=0x00007fffffff97d0,
GenCrashDiag=true) at ErrorHandling.cpp:108:5
    frame #2: 0x00007ffff1a46d51
libLLVM-12libcxx.so`llvm::report_fatal_error(Reason=<unavailable>,
GenCrashDiag=<unavailable>) at ErrorHandling.cpp:83:3
    frame #3: 0x00007ffff2bc6174
libLLVM-12libcxx.so`removeTailCallAttribute(Frame=<unavailable>,
AA=<unavailable>) at CoroElide.cpp:90:11
    frame #4: 0x00007ffff2bc48bc libLLVM-12libcxx.so`(anonymous
namespace)::Lowerer::elideHeapAllocations(this=<unavailable>, F=<unavailable>,
FrameSize=24, FrameAlign=(ShiftValue = '\x03'), AA=0x0000000001384dc0) at
CoroElide.cpp:161:3
    frame #5: 0x00007ffff2bc385a libLLVM-12libcxx.so`(anonymous
namespace)::Lowerer::processCoroId(this=0x0000000001497b00,
CoroId=0x0000000001364c20, AA=0x0000000001384dc0, DT=0x00000000013aa5a0) at
CoroElide.cpp:340:5
    frame #6: 0x00007ffff2bc64ad libLLVM-12libcxx.so`(anonymous
namespace)::CoroElideLegacy::runOnFunction(this=<unavailable>, F=<unavailable>)
at CoroElide.cpp:428:21
    frame #7: 0x00007ffff1c64f3b
libLLVM-12libcxx.so`llvm::FPPassManager::runOnFunction(this=<unavailable>,
F=0x0000000001509628) at LegacyPassManager.cpp:1440:27
    frame #8: 0x00007ffff2c5a883 libLLVM-12libcxx.so`(anonymous
namespace)::CGPassManager::RunPassOnSCC(this=0x00000000013a1d90,
P=0x00000000013a2c50, CurSCC=<unavailable>, CG=<unavailable>,
CallGraphUpToDate=0x00007fffffff9bc7, DevirtualizedCall=<unavailable>) at
CallGraphSCCPass.cpp:178:25
    frame #9: 0x00007ffff2c5a59b libLLVM-12libcxx.so`(anonymous
namespace)::CGPassManager::RunAllPassesOnSCC(this=<unavailable>,
CurSCC=<unavailable>, CG=0x0000000001367fc0,
DevirtualizedCall=0x00007fffffff9cd7) at CallGraphSCCPass.cpp:476:9
    frame #10: 0x00007ffff2c5a11c libLLVM-12libcxx.so`(anonymous
namespace)::CGPassManager::runOnModule(this=0x00000000013a1d90,
M=<unavailable>) at CallGraphSCCPass.cpp:541:18
    frame #11: 0x00007ffff1c65520 libLLVM-12libcxx.so`(anonymous
namespace)::MPPassManager::runOnModule(this=<unavailable>,
M=0x00000000002b66b0) at LegacyPassManager.cpp:1555:27
    frame #12: 0x00007ffff1c65215
libLLVM-12libcxx.so`llvm::legacy::PassManagerImpl::run(this=0x00000000013953d0,
M=0x00000000002b66b0) at LegacyPassManager.cpp:542:44
    frame #13: 0x00007ffff1c69cca
libLLVM-12libcxx.so`llvm::legacy::PassManager::run(this=<unavailable>,
M=<unavailable>) at LegacyPassManager.cpp:1682:14
    frame #14: 0x00007ffff6ed5cc6 libclang-cpp.so.12libcxx`(anonymous
namespace)::EmitAssemblyHelper::EmitAssembly(this=0x00007fffffffa368,
Action=<unavailable>, OS=<unavailable>) at BackendUtil.cpp:1012:21
    frame #15: 0x00007ffff6ed2ee2
libclang-cpp.so.12libcxx`clang::EmitBackendOutput(Diags=0x00000000002925e0,
HeaderOpts=<unavailable>, CGOpts=<unavailable>, TOpts=<unavailable>,
LOpts=<unavailable>, TDesc=0x0000000000297820, M=0x00000000002b66b0,
Action=<unavailable>, OS=<unavailable>) at BackendUtil.cpp:1580:15
    frame #16: 0x00007ffff71b6dec
libclang-cpp.so.12libcxx`clang::BackendConsumer::HandleTranslationUnit(this=<unavailable>,
C=<unavailable>) at CodeGenAction.cpp:344:7
    frame #17: 0x00007ffff622d477
libclang-cpp.so.12libcxx`clang::ParseAST(S=0x00000000002ed810,
PrintStats=<unavailable>, SkipFunctionBodies=<unavailable>) at
ParseAST.cpp:171:13
    frame #18: 0x00007ffff77ba4d2
libclang-cpp.so.12libcxx`clang::ASTFrontendAction::ExecuteAction(this=<unavailable>)
at FrontendAction.cpp:1056:3
    frame #19: 0x00007ffff71b51a1
libclang-cpp.so.12libcxx`clang::CodeGenAction::ExecuteAction(this=0x0000000000293010)
at CodeGenAction.cpp:1082:30
    frame #20: 0x00007ffff77b9e35
libclang-cpp.so.12libcxx`clang::FrontendAction::Execute(this=0x0000000000293010)
at FrontendAction.cpp:949:8
    frame #21: 0x00007ffff7776563
libclang-cpp.so.12libcxx`clang::CompilerInstance::ExecuteAction(this=0x000000000028f980,
Act=0x0000000000293010) at CompilerInstance.cpp:957:33
    frame #22: 0x00007ffff780970e
libclang-cpp.so.12libcxx`clang::ExecuteCompilerInvocation(Clang=0x000000000028f980)
at ExecuteCompilerInvocation.cpp:278:25
    frame #23: 0x000000000022ab90 clang++`cc1_main(Argv=ArrayRef<const char *>
@ 0x0000000001ccea50, Argv0="/usr/lib/llvm/12/bin/clang-12",
MainAddr=<unavailable>) at cc1_main.cpp:240:15
    frame #24: 0x0000000000223bc7
clang++`ExecuteCC1Tool(ArgV=0x00007fffffffbdb0) at driver.cpp:330:12
    frame #25: 0x00007ffff752fba2
libclang-cpp.so.12libcxx`clang::driver::CC1Command::Execute(this=0x00007fffffffbd98)
const::$_1::operator()() const at Job.cpp:404:34
    frame #26: 0x00007ffff752fb86 libclang-cpp.so.12libcxx`void
llvm::function_ref<void
()>::callback_fn<clang::driver::CC1Command::Execute(callable=<unavailable>)
const::$_1>(long) at STLExtras.h:185:12
    frame #27: 0x00007ffff1a2a7ba libLLVM-12libcxx.so`llvm::function_ref<void
()>::operator(this=<unavailable>)() const at STLExtras.h:209:12
    frame #28: 0x00007ffff1a35140
libLLVM-12libcxx.so`llvm::CrashRecoveryContext::RunSafely(this=<unavailable>,
Fn=function_ref<void ()> @ 0x00007fffffffbd38)>) at
CrashRecoveryContext.cpp:424:3
    frame #29: 0x00007ffff752ec43
libclang-cpp.so.12libcxx`clang::driver::CC1Command::Execute(this=0x000000000028f2a0,
Redirects=<unavailable>, ErrMsg=<unavailable>, ExecutionFailed=<unavailable>)
const at Job.cpp:404:12
    frame #30: 0x00007ffff75050e4
libclang-cpp.so.12libcxx`clang::driver::Compilation::ExecuteCommand(this=0x0000000000289060,
C=0x000000000028f2a0, FailingCommand=0x00007fffffffc2b0) const at
Compilation.cpp:195:15
    frame #31: 0x00007ffff7505341
libclang-cpp.so.12libcxx`clang::driver::Compilation::ExecuteJobs(this=0x0000000000289060,
Jobs=<unavailable>, FailingCommands=0x00007fffffffc470) const at
Compilation.cpp:248:19
    frame #32: 0x00007ffff7516253
libclang-cpp.so.12libcxx`clang::driver::Driver::ExecuteCompilation(this=0x00007fffffffcad8,
C=0x0000000000289060, FailingCommands=0x00007fffffffc470) at Driver.cpp:1514:5
    frame #33: 0x0000000000223225 clang++`main(argc_=<unavailable>,
argv_=<unavailable>) at driver.cpp:502:21
    frame #34: 0x00007fffedf87e3a libc.so.6`__libc_start_main + 234
    frame #35: 0x00000000002222ba clang++`_start + 42

The bug happens with -O2, -O3 and -Os, but not at -O0 or -O1.

I tried to fix this by modifying the code with FIXME that removes tailcall
attributes, but currently trips on musttail in two ways:
- replace report_fatal_error with continue to keep musttail attribute in place;
- remove the check for musttail, so it does get removed.
I've checked these versions on my original code which triggers this bug, both
variants fix the crash and produce valid binaries that pass tests under
ASAN/UBSAN, the only difference in assembly is that the first version indeed
uses a tail call, which is slightly more optimal.
I don't know enough to say whether this is a right general fix.
Looks like a lot has changed in LLVM in 4 years since this was originally
written in regards to coroutine handling.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20201230/8f67025c/attachment-0001.html>


More information about the llvm-bugs mailing list