[Bug c++/95822] New: [coroutines] compiler internal error with local object with noexcept false destructor

2020-06-22 Thread victor.burckel at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95822

Bug ID: 95822
   Summary: [coroutines] compiler internal error with local object
with noexcept false destructor
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

It seems that when a coroutine contains a local object whose destructor is
marked as noexcept(false), gcc reaches an unexpected state and aborts.
When compiling the following code with gcc10.1.0 (-std=c++20 -fcoroutines), I
get a compiler internal error: 
> internal compiler error: in gimplify_var_or_parm_decl, at gimplify.c:2830

Making the destructor noexcept fixes the error. I  got the error when using
boost log within a couroutine. It uses a record_pump whose destructor is not
noexcept.

I managed to reproduce with godbolt (both gcc10.1 and gcc trunk give me the
assertion)
https://godbolt.org/z/6JtKsU

#include 

struct task {
  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_void() {}
task get_return_object() { return task{}; }
void unhandled_exception() noexcept {}
  };

  ~task() noexcept {}

  bool await_ready() const noexcept { return false; }
  void await_suspend(std::coroutine_handle<>) noexcept {}
  void await_resume() noexcept {}
};

struct Error {
  ~Error() noexcept(false) {}
};

task g();
task f() {
  Error error;
  co_await g();
}

[Bug c++/95823] New: [coroutines] compiler internal error in captures_temporary,

2020-06-22 Thread victor.burckel at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95823

Bug ID: 95823
   Summary: [coroutines] compiler internal error in
captures_temporary,
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

I get a compiler internal error when passing a value to a coroutine that is
retrieved through two inderections within smart pointers (I don't get the error
with raw pointers, that's the smallest piece of code I was able to produce).
> internal compiler error: in captures_temporary, at cp/coroutines.cc:2717

It can be easily worked around by making a local variable containing the value.
Of course the code would crash in runtime as the pointers are not initialized,
but I get the same error when initializing them.

I managed to reproduce with godbolt (both gcc10.1 and gcc trunk give me the
assertion)
https://godbolt.org/z/XarC_M

#include 
#include 

struct task {
  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_void() {}
task get_return_object() { return task{}; }
void unhandled_exception() noexcept {}
  };

  ~task() noexcept {}

  bool await_ready() const noexcept { return false; }
  void await_suspend(std::coroutine_handle<>) noexcept {}
  void await_resume() noexcept {}
};

struct Id
{
std::unique_ptr value;
};

task g(int);

task f() {
std::unique_ptr id;
co_await g(*id->value);
}

[Bug c++/95824] New: [coroutines] compiler crash

2020-06-22 Thread victor.burckel at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95824

Bug ID: 95824
   Summary: [coroutines] compiler crash
   Product: gcc
   Version: 10.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

The following code sample makes the gcc 10.1.0 compiler crash with segmentation
fault (compiled with -std=c++20 -fcoroutines). Gcc trunk generates an assertion
> internal compiler error: tree check: expected function_type or method_type, 
> have pointer_type in captures_temporary, at cp/coroutines.cc:2690

That's the smallest piece of code I was able to reproduce on gcc 10.1.0
(removing the virtual from the makeId method or removing the virtual
inheritance from the exception fixes the issue). 
On gcc trunk the exception and base classes are not necessary to generate the
assertion.

I initially got this issue when invoking a virtual method to get a feed a
parameter to a coroutine, with boost::archive::archive_exception included,
which virtually inherits from std::exception.

I managed to reproduce with godbolt
https://godbolt.org/z/tBmRxJ

#include 

struct task {
  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_void() {}
task get_return_object() { return task{}; }
void unhandled_exception() noexcept {}
  };

  ~task() noexcept {}

  bool await_ready() const noexcept { return false; }
  void await_suspend(std::coroutine_handle<>) noexcept {}
  void await_resume() noexcept {}
};

struct base
{
virtual ~base() = default;
};

class exception : public virtual base
{};

struct factory
{
virtual ~factory() = default;
virtual int makeId() const;
};

task g(int);

task f(factory& factory) {
co_await g(factory.makeId());
}

[Bug c++/101144] New: Coroutine compiler error

2021-06-21 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101144

Bug ID: 101144
   Summary: Coroutine compiler error
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

Hello,

When trying to await the following coroutine, I get a compiler internal error
> internal compiler error: in build_special_member_call, at cp/call.c:10157

See it on godbolt: https://godbolt.org/z/f178vEqc9

#include 
#include 
#include 

struct task {
  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_void() {}
task get_return_object() { return task{}; }
void unhandled_exception() noexcept {}
  };

  ~task() noexcept {}

  bool await_ready() const noexcept { return false; }
  void await_suspend(std::coroutine_handle<>) noexcept {}
  void await_resume() noexcept {}
};

task f(const std::vector&)
{
co_return;
}

task g()
{
co_await f({"2", "3"});
}

[Bug c++/101149] New: Coroutine compiler error with ternary operator

2021-06-21 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101149

Bug ID: 101149
   Summary: Coroutine compiler error with ternary operator
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

Hello, 

I'm getting a compiler error when trying to use co_await expression in a
ternary operator:
> internal compiler error: in expand_expr_real_1, at expr.c:10285

See on godbolt https://godbolt.org/z/Wfva333cc

#include 
#include 
#include 

struct task {
  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_value(int) {}
task get_return_object() { return task{}; }
void unhandled_exception() noexcept {}
  };

  ~task() noexcept {}

  bool await_ready() const noexcept { return false; }
  void await_suspend(std::coroutine_handle<>) noexcept {}
  int await_resume() noexcept { return 1; }
};

task f(int)
{
co_return 1;
}

task g(bool b)
{
auto result = b ? co_await f(1) : 2;
}

[Bug c++/99576] [coroutines] destructor of a temporary called too early within co_await expression

2021-06-23 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99576

--- Comment #4 from Victor Burckel  ---
I'm also seeing the same behavior, destructor of lambda captures seems to get
called twice
https://godbolt.org/z/zxnhM3x47

[Bug c++/98401] Temporaries passed to co_await sometimes cause an extraneous call to destructor at incorrect address

2021-06-23 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98401

Victor Burckel  changed:

   What|Removed |Added

 CC||victor.burckel at gmail dot com

--- Comment #4 from Victor Burckel  ---
I'm also seeing the same behavior, destructor of lambda captures seems to get
called twice
https://godbolt.org/z/zxnhM3x47

[Bug c++/101243] New: Coroutine lambda capture is destroyed twice

2021-06-28 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101243

Bug ID: 101243
   Summary: Coroutine lambda capture is destroyed twice
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

In a corourtine expecting a std::function parameter, passing a
temporary lambda with a capture results in the capture being destroyed twice:
See it on gldbolt, gcc vs clang outputs
https://godbolt.org/z/jx9Yh5cqM

#include 

#include 
#include 

#ifdef __clang__
namespace std::experimental {
using std::coroutine_handle;
using std::coroutine_traits;
}  // namespace std::experimental
#endif

struct task {
  struct promise_type;
  using handle_type = std::coroutine_handle;

  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_void() noexcept {}
task get_return_object() noexcept {
  return task{handle_type::from_promise(*this)};
}
void unhandled_exception() noexcept {}
  };

  task(handle_type h) : h{h} {}
  ~task() {
if (h) {
  fmt::print("destroying coroutine\n");
  h.destroy();
  fmt::print("coroutine destroyed\n");
}
  }

  bool await_ready() const noexcept { return false; }
  bool await_suspend(std::coroutine_handle<>) noexcept {
h.resume();
return true;
  }
  void await_resume() noexcept {}

  void resume() { h.resume(); }

  handle_type h;
};

struct S {
  S() { fmt::print("S::S()\n"); }
  S(const S&) { fmt::print("S::S(const S&)\n"); }
  S(S&&) { fmt::print("S::S(S&&)\n"); }
  ~S() { fmt::print("S::~S()\n"); }
};

task g(std::function) {
  fmt::print("in g()\n");
  co_return;
}

task f() {
  fmt::print("calling g()\n");
  co_await g([s=S{}] {});
  fmt::print("g called\n");
}

int main() {
  auto task = f();
  fmt::print("resuming f\n");
  task.resume();
  fmt::print("resuming f\n");
  task.resume();
}

Gcc outputs:
resuming f
calling g()
S::S()
S::S(S&&)
in g()
resuming f
destroying coroutine
S::~S()
coroutine destroyed
S::~S()
S::~S()
g called
destroying coroutine
coroutine destroyed

While clang outputs:
resuming f
calling g()
S::S()
S::S(S&&)
in g()
resuming f
destroying coroutine
S::~S()
coroutine destroyed
S::~S()
g called
destroying coroutine
coroutine destroyed

[Bug c++/101243] Coroutine lambda capture is destroyed twice

2021-06-28 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101243

--- Comment #1 from Victor Burckel  ---
May be similar to 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99576
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98401

[Bug c++/101244] New: Wrong path in coroutine returning ternary

2021-06-28 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101244

Bug ID: 101244
   Summary: Wrong path in coroutine returning ternary
   Product: gcc
   Version: 11.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: victor.burckel at gmail dot com
  Target Milestone: ---

In a coroutine returning a ternary expression with co_await, the co_await part
seems to be evaluated whatever the result of the condition:
See it on godbolt, I added a check of coro.done in the resume operation to
avoid a crash in the clang part as the coroutine is voluntarily resumed one
extra time
https://godbolt.org/z/vzGKoP8d3

#include 

#include 
#include 

#ifdef __clang__
namespace std::experimental {
using std::coroutine_handle;
using std::coroutine_traits;
}  // namespace std::experimental
#endif

struct task {
  struct promise_type;
  using handle_type = std::coroutine_handle;

  struct promise_type {
auto initial_suspend() noexcept { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void return_value(int v) noexcept { value = v; }
task get_return_object() noexcept {
  return task{handle_type::from_promise(*this)};
}
void unhandled_exception() noexcept {}

int value{};
  };

  task(handle_type h) : h{h} {}
  ~task() {
if (h) {
  fmt::print("destroying coroutine\n");
  h.destroy();
  fmt::print("coroutine destroyed\n");
}
  }

  bool await_ready() const noexcept { return false; }
  bool await_suspend(std::coroutine_handle<>) noexcept {
h.resume();
return true;
  }
  int await_resume() noexcept { return h.promise().value; }

  void resume() {
if (!h.done()) h.resume();
  }

  handle_type h;
};

struct S {
  S() { fmt::print("S::S()\n"); }
  S(const S&) { fmt::print("S::S(const S&)\n"); }
  S(S&&) { fmt::print("S::S(S&&)\n"); }
  ~S() { fmt::print("S::~S()\n"); }
};

task g(S) {
  fmt::print("in g()\n");
  co_return 1;
}

task f(bool b) {
  fmt::print("calling g()\n");
  co_return b ? co_await g(S{}) : 2;
}

int main() {
  auto task = f(false);
  fmt::print("resuming f\n");
  task.resume();
  fmt::print("resuming f\n");
  task.resume();
}

Gcc outputs
resuming f
calling g()
S::S()
S::S(S&&)
in g()
resuming f
destroying coroutine
S::~S()
coroutine destroyed
S::~S()
destroying coroutine
coroutine destroyed

While clang outputs
resuming f
calling g()
resuming f
destroying coroutine
coroutine destroyed

[Bug c++/101244] Wrong path in coroutine returning ternary

2021-06-28 Thread victor.burckel at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101244

--- Comment #1 from Victor Burckel  ---
If ternary is not put in the co_return part but split into assignement return,
the compiler crashes
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101149