llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.56k stars 11.81k forks source link

clang fails to diagnose a co_await in a default argument, and ICEs if the default argument is used in a lambda #98923

Open ArsenArsen opened 3 months ago

ArsenArsen commented 3 months ago

we received PR115906 in GCC, which presented the following code:

#include <coroutine>

struct Promise;

struct Handle : std::coroutine_handle<Promise> {
    using promise_type = Promise;
};

struct Promise {
    Handle get_return_object() noexcept {
        return {Handle::from_promise(*this)};
    }
    std::suspend_never initial_suspend() const noexcept { return {}; }
    std::suspend_never final_suspend() const noexcept { return {}; }
    void return_void() const noexcept {}
    void unhandled_exception() const noexcept {}
};

Handle Coro() {
    struct Awaiter : std::suspend_never {
        int await_resume() { return 0; }
    };

    void foo(int = co_await Awaiter{});
#if 0 // flip on for ICE
    [] { foo(); } ();
#endif
    co_return;
}

int main() {
    Coro();

    return 0;
}

... this is invalid per https://eel.is/c++draft/expr.await#2 but clang does not diagnose it.

before realizing that, I was checking what clang and MSVC do in this case. clang accepted this code, as I said, and had it DTRT in the basic case; MSVC rejected it.

I was further tweaking the code a bit and discovered that I can get clang to crash by adding the IILE above (presumably, any non-coroutine or perhaps a different coroutine with foo in scope would have done, but I have not tried).

llvmbot commented 3 months ago

@llvm/issue-subscribers-coroutines

Author: Arsen Arsenović (ArsenArsen)

we received [PR115906](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115906) in GCC, which presented the following code: ```c++ #include <coroutine> struct Promise; struct Handle : std::coroutine_handle<Promise> { using promise_type = Promise; }; struct Promise { Handle get_return_object() noexcept { return {Handle::from_promise(*this)}; } std::suspend_never initial_suspend() const noexcept { return {}; } std::suspend_never final_suspend() const noexcept { return {}; } void return_void() const noexcept {} void unhandled_exception() const noexcept {} }; Handle Coro() { struct Awaiter : std::suspend_never { int await_resume() { return 0; } }; void foo(int = co_await Awaiter{}); #if 0 // flip on for ICE [] { foo(); } (); #endif co_return; } int main() { Coro(); return 0; } ``` ... this is invalid per https://eel.is/c++draft/expr.await#2 but clang does not diagnose it. before realizing that, I was checking what clang and MSVC do in this case. clang accepted this code, as I said, and had it DTRT in the basic case; MSVC rejected it. I was further tweaking the code a bit and discovered that I can get clang to crash by adding the IILE above (presumably, any non-coroutine or perhaps a different coroutine with `foo` in scope would have done, but I have not tried).
llvmbot commented 3 months ago

@llvm/issue-subscribers-clang-frontend

Author: Arsen Arsenović (ArsenArsen)

we received [PR115906](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115906) in GCC, which presented the following code: ```c++ #include <coroutine> struct Promise; struct Handle : std::coroutine_handle<Promise> { using promise_type = Promise; }; struct Promise { Handle get_return_object() noexcept { return {Handle::from_promise(*this)}; } std::suspend_never initial_suspend() const noexcept { return {}; } std::suspend_never final_suspend() const noexcept { return {}; } void return_void() const noexcept {} void unhandled_exception() const noexcept {} }; Handle Coro() { struct Awaiter : std::suspend_never { int await_resume() { return 0; } }; void foo(int = co_await Awaiter{}); #if 0 // flip on for ICE [] { foo(); } (); #endif co_return; } int main() { Coro(); return 0; } ``` ... this is invalid per https://eel.is/c++draft/expr.await#2 but clang does not diagnose it. before realizing that, I was checking what clang and MSVC do in this case. clang accepted this code, as I said, and had it DTRT in the basic case; MSVC rejected it. I was further tweaking the code a bit and discovered that I can get clang to crash by adding the IILE above (presumably, any non-coroutine or perhaps a different coroutine with `foo` in scope would have done, but I have not tried).