[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-16 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #8 from GCC Commits  ---
The trunk branch has been updated by Marek Polacek :

https://gcc.gnu.org/g:254ff3d0e34835b4de93d5e5763a7366dc7d989d

commit r14-9034-g254ff3d0e34835b4de93d5e5763a7366dc7d989d
Author: Marek Polacek 
Date:   Wed Feb 14 17:53:52 2024 -0500

c++: implicit move with throw [PR113853]

Here we have

  template
  auto is_throwable(T t) -> decltype(throw t, true) { ... }

where we didn't properly mark 't' as IMPLICIT_RVALUE_P, which caused
the wrong overload to have been chosen.  Jason figured out it's because
we don't correctly implement [expr.prim.id.unqual]#4.2, which post-P2266
says that an id-expression is move-eligible if

"the id-expression (possibly parenthesized) is the operand of
a throw-expression, and names an implicitly movable entity that belongs
to a scope that does not contain the compound-statement of the innermost
lambda-expression, try-block, or function-try-block (if any) whose
compound-statement or ctor-initializer contains the throw-expression."

I worked out that it's trying to say that given

  struct X {
X();
X(const X&);
X(X&&) = delete;
  };

the following should fail: the scope of the throw is an sk_try, and it's
also x's scope S, and S "does not contain the compound-statement of the
*try-block" so x is move-eligible, so we move, so we fail.

  void f ()
  try {
X x;
throw x;  // use of deleted function
  } catch (...) {
  }

Whereas here:

  void g (X x)
  try {
throw x;
  } catch (...) {
  }

the throw is again in an sk_try, but x's scope is an sk_function_parms
which *does* contain the {} of the *try-block, so x is not move-eligible,
so we don't move, so we use X(const X&), and the code is fine.

The current code also doesn't seem to handle

  void h (X x) {
void z (decltype(throw x, true));
  }

where there's no enclosing lambda or sk_try so we should move.

I'm not doing anything about lambdas because we shouldn't reach the
code at the end of the function: the DECL_HAS_VALUE_EXPR_P check
shouldn't let us go further.

PR c++/113789
PR c++/113853

gcc/cp/ChangeLog:

* typeck.cc (treat_lvalue_as_rvalue_p): Update code to better
reflect [expr.prim.id.unqual]#4.2.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/sfinae69.C: Remove dg-bogus.
* g++.dg/cpp0x/sfinae70.C: New test.
* g++.dg/cpp0x/sfinae71.C: New test.
* g++.dg/cpp0x/sfinae72.C: New test.
* g++.dg/cpp2a/implicit-move4.C: New test.

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-10 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #7 from Marek Polacek  ---
The ICE was fixed by r14-8903-g3a3e0f1b46a3ad.  But I'm not done here yet.

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-06 Thread arthur.j.odwyer at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #6 from Arthur O'Dwyer  ---
(In reply to Marek Polacek from comment #5)
> IOW, this should be accepted in C++23 but isn't (clang++ accepts in C++23): 
> [...]

Correct, at least that's my intended interpretation. But the unexpected ICE was
more dramatic. :)
I'd be a tiny bit surprised if fixing `decltype(throw p)` actually closes the
only pathway to that ICE; but if it does, then awesome, I have no complaints.

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-06 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #5 from Marek Polacek  ---
IOW, this should be accepted in C++23 but isn't (clang++ accepts in C++23):

struct AutoPtr {
AutoPtr() = default;
AutoPtr(AutoPtr&) {}
};

template auto f(T p, int) -> decltype(throw p, 1) = delete;
template void f(T p, long);

void
g ()
{
  f (AutoPtr (), 42);
}

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-06 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #4 from Marek Polacek  ---
Um, that's not it.  Since

struct AutoPtr {
AutoPtr() = default;
AutoPtr(AutoPtr&) {}
};

template int
f (T p)
{
  throw p;
}

void
g ()
{
  f (AutoPtr ());
}

is rejected in C++23, we probably should have rejected the decltype(throw p, 1)
candidate and never get to the throw in the body of the function f.

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-06 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

--- Comment #3 from Marek Polacek  ---
I have a patch for the ICE (build_throw doesn't have a complain param so we
wind up with "error reporting routines re-entered").

[Bug c++/113789] [13/14 Regression] ICE on P2266/C++23 `decltype(throw x)` where x is move-eligible parameter

2024-02-06 Thread mpolacek at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113789

Marek Polacek  changed:

   What|Removed |Added

Summary|ICE on P2266/C++23  |[13/14 Regression] ICE on
   |`decltype(throw x)` where x |P2266/C++23 `decltype(throw
   |is move-eligible parameter  |x)` where x is
   ||move-eligible parameter
   Target Milestone|--- |13.3
   Priority|P3  |P2