Message ID | 20160727120502.GV4264@redhat.com |
---|---|
State | New |
Headers | show |
On Wed, Jul 27, 2016 at 8:05 AM, Jonathan Wakely <jwakely@redhat.com> wrote: > Consider: > > template<typename T> T declval(); > > int& r1 = declval<int&&>(); > int&& r2 = declval<int&>(); > int& r3 = declval<const int&>(); > > > This produces three quite different errors: > > > refs.cc:3:25: error: invalid initialization of non-const reference of type > 'int&' from an rvalue of type 'int' > int& r1 = declval<int&&>(); > ~~~~~~~~~~~~~~^~ > refs.cc:4:25: error: cannot bind 'int' lvalue to 'int&&' > int&& r2 = declval<int&>(); > ~~~~~~~~~~~~~^~ > refs.cc:5:30: error: binding 'const int' to reference of type 'int&' > discards qualifiers > int& r3 = declval<const int&>(); > ~~~~~~~~~~~~~~~~~~~^~ > > > The first one uses the order to/from, but the other two are from/to. > > The first and second are saying the same thing (wrong value category) > but very differently. > > The first and third mention references but the second doesn't. > > The standard talks about binding a reference to something, but the > second and third diagnostics talk about binding something to a > reference (and the first doesn't mention binding at all). > > The first diagnostic is specific to lvalue references (it wouldn't be > invalid if it was binding a non-const _rvalue_ reference to an > rvalue), but doesn't use the word "lvalue". > > (FWIW Clang and EDG both have their own inconsistencies for the same > example, but that shouldn't stop us trying to improve.) > > > IMHO the first should use the words "bind" and "lvalue reference": > > refs.cc:3:25: error: cannot bind non-const lvalue reference of type 'int&' > to an rvalue of type 'int' > int& r1 = declval<int&&>(); > ~~~~~~~~~~~~~~^~ > > The second should use the phrasing "bind ref to value" instead of > "bind value to ref", and mention "rvalue reference": > > refs.cc:4:25: error: cannot bind rvalue reference of type 'int&&' to an > lvalue of type 'int' > int&& r2 = declval<int&>(); > ~~~~~~~~~~~~~^~ > > The third should use the same phrasing (but doesn't need to mention > lvalue/rvalue because the problem is related to cv-qualifiers not > value categories): > > refs.cc:5:30: error: binding reference of type 'int&' to 'const int' > discards qualifiers > int& r3 = declval<const int&>(); > ~~~~~~~~~~~~~~~~~~~^~ > > > I've only considered trivial examples here, is there some reason to > prefer to current diagnostics for more complex cases? > > The attached patch makes that change, but there are probably lots of > tests that would need updating which I haven't done until I know if > the change is worthwhile. Sounds good to me. Jason
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 802c325..918661a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6710,15 +6710,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree extype = TREE_TYPE (expr); if (TYPE_REF_IS_RVALUE (ref_type) && lvalue_p (expr)) - error_at (loc, "cannot bind %qT lvalue to %qT", - extype, totype); + error_at (loc, "cannot bind rvalue reference of type %qT to " + "lvalue of type %qT", totype, extype); else if (!TYPE_REF_IS_RVALUE (ref_type) && !lvalue_p (expr) && !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))) - error_at (loc, "invalid initialization of non-const reference of " - "type %qT from an rvalue of type %qT", totype, extype); + error_at (loc, "cannot bind non-const lvalue reference of " + "type %qT to an rvalue of type %qT", totype, extype); else if (!reference_compatible_p (TREE_TYPE (totype), extype)) - error_at (loc, "binding %qT to reference of type %qT " - "discards qualifiers", extype, totype); + error_at (loc, "binding reference of type %qT to %qT " + "discards qualifiers", totype, extype); else gcc_unreachable (); maybe_print_user_conv_context (convs);