https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77733
David Malcolm <dmalcolm at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |dmalcolm at gcc dot gnu.org --- Comment #3 from David Malcolm <dmalcolm at gcc dot gnu.org> --- (In reply to Jonathan Wakely from comment #2) > The location for the "cannot bind rvalue reference" error is not a rich > location, so I couldn't figure out how to add a proper fix-it. It's trivial to get a rich_location from a location_t: rich_location richloc (loc); // maybe add some fixits to richloc here... error_at_rich_loc (&richloc, "cannot bind..." etc etc An issue here is that "loc" isn't a good enough location_t: in convert_like_real it comes from: location_t loc = EXPR_LOC_OR_LOC (expr, input_location); In the example, expr is a VAR_DECL and uses of decls don't have locations, so it uses input_location for "loc", putting it on the closing paren of the call: /tmp/test.cc: In function ‘int main()’: /tmp/test.cc:14:10: error: cannot bind rvalue reference of type ‘X&&’ to lvalue of type ‘X’ y.foo(x); ^ If loc had a meaningful location for x, you could use something like,: richloc.add_fixit_insert_before (loc, "std::move ("); richloc.add_fixit_insert_after (loc, ")"); The "not every expression has a location_t" is PR 43486 - maybe this should be a dependency of that bug? (unless there's some way to ensure that all callers of convert_like_real preserve the location information from the cp_expr in the C++ parser). (I've been experimenting with ideas for fixing PR 43486, but it's unlikely to make it for gcc 7). > This just adds "did you mean std::move(x)?" to the end: > > --- a/gcc/cp/call.c > +++ b/gcc/cp/call.c > @@ -6804,7 +6804,8 @@ convert_like_real (conversion *convs, tree expr, tree > fn, int argnum, > if (TYPE_REF_IS_RVALUE (ref_type) > && lvalue_p (expr)) > error_at (loc, "cannot bind rvalue reference of type %qT to " > - "lvalue of type %qT", totype, extype); > + "lvalue of type %qT; did you mean > %<std::move(%E)%>?", > + totype, extype, expr); > else if (!TYPE_REF_IS_RVALUE (ref_type) && !lvalue_p (expr) > && !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))) > error_at (loc, "cannot bind non-const lvalue reference of " FWIW, I'm not sure we want to add uses of %E to the compiler; my recollection is that it can lead to poor output for the more complicated cases. > Of course sometimes std::move is not the right fix, and it should be > std::forward<something>(x) instead. Maybe it would be possible to detect > whether the expression is a function parameter declared as a forwarding > reference, but that's probably beyond my ken. > Also, if the lvalue is cv-qualified this still suggests std::move(x) even > when that wouldn't work: > > move2.cc:13:9: error: cannot bind rvalue reference of type ‘X&&’ to lvalue > of type ‘const X’; did you mean ‘std::move(x)’? > > > There's room for improvement. (nods)