Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REQUIRE(co_await expr) unexpectedly repeats execution in GCC #2925

Open
Hackerl opened this issue Oct 26, 2024 · 2 comments
Open

REQUIRE(co_await expr) unexpectedly repeats execution in GCC #2925

Hackerl opened this issue Oct 26, 2024 · 2 comments

Comments

@Hackerl
Copy link

Hackerl commented Oct 26, 2024

Describe the bug
REQUIRE(co_await expr) unexpectedly repeats execution in GCC.

Expected behavior
The co_await expression should only be executed once

Reproduction steps
https://godbolt.org/z/h6jshrYs8

#include <iostream>
#include <coroutine>
#include <https://raw.githubusercontent.com/catchorg/Catch2/refs/tags/v3.7.1/extras/catch_amalgamated.hpp>
#include <https://raw.githubusercontent.com/catchorg/Catch2/refs/tags/v3.7.1/extras/catch_amalgamated.cpp>

struct promise;

struct coroutine : std::coroutine_handle<promise> {
    using promise_type = ::promise;
};

struct promise {
    coroutine get_return_object() { return {coroutine::from_promise(*this)}; }
    std::suspend_never initial_suspend() noexcept { return {}; }
    std::suspend_never final_suspend() noexcept { return {}; }

    void return_void() {
    }

    void unhandled_exception() {
    }
};

struct Awaitable {
    bool await_ready() {
        static int counter{};
        std::cout << ++counter << std::endl;
        return true;
    }

    void await_suspend(std::coroutine_handle<>) {
    }

    bool await_resume() {
        return true;
    }
};

coroutine test() {
    REQUIRE(co_await Awaitable{});
}

TEST_CASE("test") {
    test();
}

Platform information:

  • OS: Any
  • Compiler+version: GCC v14.x.x
  • Catch version: v3.7.1

Additional context
In GCC, __builtin_constant_p(co_await expr) is executed unexpectedly.
while ((void) 0, (false) && static_cast<const bool &>(!!(co_await expr))) is also.
I believe this is a compiler bug, but is there a way to avoid it with catch?

@horenmar
Copy link
Member

Well, that's not the funniest bug with __builtin_constant_p I've seen*, but this is the first time GCC has one. Currently there isn't a configuration option to disable this, but seeing this, I think that it is either time to add one, or to remove that check completely.

Have you reported this to GCC bugzilla?

* That goes to IBM XL, which would generate a call to the destructor of a temporary, without generating the constructor 😃

horenmar added a commit that referenced this issue Oct 27, 2024
Turns out that even in GCC, the expression in `__builtin_cosntant_p`
can end up evaluated and side-effects executed. To allow users to
work around this bug, I added a configuration option to disable its
use in internal macros.

Related to #2925
@horenmar
Copy link
Member

GCC already has two bugs for this upstream

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116775 and https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101027

horenmar added a commit that referenced this issue Oct 27, 2024
Turns out that even in GCC, the expression in `__builtin_cosntant_p`
can end up evaluated and side-effects executed. To allow users to
work around this bug, I added a configuration option to disable its
use in internal macros.

Related to #2925
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants