Skip to content

Commit

Permalink
c++: reference cast, conversion fn [PR113141]
Browse files Browse the repository at this point in the history
The second testcase in 113141 is a separate issue: we first decide that the
conversion is ill-formed, but then when recalculating the special c_cast_p
handling makes us think it's OK.  We don't want that, it should continue to
fall back to the reinterpret_cast interpretation.  And while we're here,
let's warn that we're not using the conversion function.

Note that the standard seems to say that in this case we should
treat (Matrix &) as const_cast<Matrix &>(static_cast<const Matrix &>(X)),
which would use the conversion operator, but that doesn't match existing
practice, so let's resolve that another day.  I've raised this issue with
CWG; at the moment I lean toward never binding a temporary in a C-style cast
to reference type, which would also be a change from existing practice.

	PR c++/113141

gcc/c-family/ChangeLog:

	* c.opt: Add -Wcast-user-defined.

gcc/ChangeLog:

	* doc/invoke.texi: Document -Wcast-user-defined.

gcc/cp/ChangeLog:

	* call.cc (reference_binding): For an invalid cast, warn and don't
	recalculate.

gcc/testsuite/ChangeLog:

	* g++.dg/conversion/ref12.C: New test.

Co-authored-by: Patrick Palka <ppalka@redhat.com>
  • Loading branch information
jicama and Patrick Palka committed Apr 12, 2024
1 parent d435571 commit df7bfdb
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 1 deletion.
4 changes: 4 additions & 0 deletions gcc/c-family/c.opt
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ Wcast-qual
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
Warn about casts which discard qualifiers.

Wcast-user-defined
C++ ObjC++ Var(warn_cast_user_defined) Warning Init(1)
Warn about a cast to reference type that does not use a related user-defined conversion function.

Wcatch-value
C++ ObjC++ Warning Alias(Wcatch-value=, 1, 0)
Warn about catch handlers of non-reference type.
Expand Down
12 changes: 11 additions & 1 deletion gcc/cp/call.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2034,7 +2034,17 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
recalculate the second conversion sequence. */
for (conversion *t = conv; t; t = next_conversion (t))
if (t->kind == ck_user
&& DECL_CONV_FN_P (t->cand->fn))
&& c_cast_p && !maybe_valid_p)
{
if (complain & tf_warning)
warning (OPT_Wcast_user_defined,
"casting %qT to %qT does not use %qD",
from, rto, t->cand->fn);
/* Don't let recalculation try to make this valid. */
break;
}
else if (t->kind == ck_user
&& DECL_CONV_FN_P (t->cand->fn))
{
tree ftype = TREE_TYPE (TREE_TYPE (t->cand->fn));
/* A prvalue of non-class type is cv-unqualified. */
Expand Down
13 changes: 13 additions & 0 deletions gcc/doc/invoke.texi
Original file line number Diff line number Diff line change
Expand Up @@ -9391,6 +9391,19 @@ In a cast involving pointer to member types this warning warns whenever
the type cast is changing the pointer to member type.
This warning is enabled by @option{-Wextra}.

@opindex Wcast-user-defined
@opindex Wno-cast-user-defined
@item -Wcast-user-defined
Warn when a cast to reference type does not involve a user-defined
conversion that the programmer might expect to be called.

@smallexample
struct A @{ operator const int&(); @} a;
auto r = (int&)a; // warning
@end smallexample

This warning is enabled by default.

@opindex Wwrite-strings
@opindex Wno-write-strings
@item -Wwrite-strings
Expand Down
20 changes: 20 additions & 0 deletions gcc/testsuite/g++.dg/conversion/ref12.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// PR c++/113141

struct Matrix { };

struct TPoint3 { private: operator const Matrix(); };

void f(Matrix&);

int main() {
TPoint3 X;
Matrix& m = (Matrix &)X; // { dg-warning "does not use" }
f((Matrix &)X); // { dg-warning "does not use" }
}

struct A { private: operator const int&(); } a;
int &r = (int&)a; // { dg-warning "does not use" }

struct B { B(int); };
int i;
B &br = (B&)i; // { dg-warning "does not use" }

0 comments on commit df7bfdb

Please sign in to comment.