[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely  changed:

   What|Removed |Added

 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED
   Target Milestone|--- |9.0

--- Comment #13 from Jonathan Wakely  ---
Fixed for gcc 9.

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #14 from Jonathan Wakely  ---
Author: redi
Date: Mon Dec 17 21:49:58 2018
New Revision: 267219

URL: https://gcc.gnu.org/viewcvs?rev=267219=gcc=rev
Log:
PR c++/52321 print note for static_cast to/from incomplete type

PR c++/52321
* typeck.c (build_static_cast): Print a note when the destination
type or the operand is a pointer/reference to incomplete class type.

Added:
trunk/gcc/testsuite/g++.dg/expr/static_cast8.C
Modified:
trunk/gcc/cp/ChangeLog
trunk/gcc/cp/typeck.c

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #12 from Jonathan Wakely  ---
(In reply to Ivan Godard from comment #4)
> Define an enum of reasons with "success" first, flop the sense of the test
> so that false means coercion was OK (grep to find all calls and put a "!" in
> front of each), and return the reason enum instead of bool. The code that is
> reason-aware saves the enum and builds a good message; the legacy code that
> is not reason-aware treats the enum as a bool and works as before except for
> the inverted sense of the test. Maybe half an hour of work.

A much simpler "good enough" solution is to just leave build_static_cast_1
alone. In the caller, if the cast fails and one or both types is a
pointer/reference to incomplete class, issue a note. It doesn't matter if the
reason it failed is the incomplete type, because I don't try to say that, I
just say it's incomplete.

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely  changed:

   What|Removed |Added

   Keywords||patch
 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |redi at gcc dot gnu.org

--- Comment #11 from Jonathan Wakely  ---
Patch tested and posted to
https://gcc.gnu.org/ml/gcc-patches/2018-12/msg01228.html

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #10 from Jonathan Wakely  ---
Untested patch:

--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7348,8 +7348,19 @@ build_static_cast (tree type, tree oexpr, tsubst_flags_t
complain)
 }

   if (complain & tf_error)
-error ("invalid static_cast from type %qT to type %qT",
-   TREE_TYPE (expr), type);
+{
+  error ("invalid static_cast from type %qT to type %qT",
+TREE_TYPE (expr), type);
+  if ((TYPE_PTR_P (type) || TYPE_REF_P (type))
+ || !COMPLETE_TYPE_P (TREE_TYPE (type)))
+   inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (TREE_TYPE (type))),
+   "class type %qT is incomplete", TREE_TYPE (type));
+  tree expr_type = TREE_TYPE (expr);
+  if ((TYPE_PTR_P (expr_type) || TYPE_REF_P (expr_type))
+ || !COMPLETE_TYPE_P (TREE_TYPE (expr_type)))
+   inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (TREE_TYPE (expr_type))),
+   "class type %qT is incomplete", TREE_TYPE (expr_type));
+}
   return error_mark_node;
 }


For the original example this produces:

53231.cc: In function 'int main()':
53231.cc:5:31: error: invalid static_cast from type 'foo*' to type 'bar*'
5 |   bar* b = static_cast(f);
  |   ^
53231.cc:1:7: note: class type 'foo' is incomplete
1 | class foo;
  |   ^~~


And for the example from Bug 88503:

88503.cc: In function 'Derived* foo(Parent*)':
88503.cc:6:39: error: invalid static_cast from type 'Parent*' to type
'Derived*'
6 | return static_cast(p);
  |   ^
88503.cc:2:7: note: class type 'Derived' is incomplete
2 | class Derived;
  |   ^~~
88503.cc:1:7: note: class type 'Parent' is incomplete
1 | class Parent;
  |   ^~

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #9 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #8)
> Clang outputs an extra line saying the type is incomplete (which should
> probably be a "note:" but nevermind):

Ha, it is a note, but on my terminal the "note:" part is shown as black text on
a black background. It only showed up when I pasted it in here!

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2018-12-17
 Ever confirmed|0   |1

--- Comment #8 from Jonathan Wakely  ---
Clang outputs an extra line saying the type is incomplete (which should
probably be a "note:" but nevermind):

53231.cc:5:17: error: static_cast from 'foo *' to 'bar *', which are not
related by inheritance, is not allowed
   bar* b = static_cast(f);
^~~~
53231.cc:1:7: note: 'foo' is incomplete
class foo;
  ^
1 error generated.


When both types are incomplete it says that too:

88503.cc:6:16: error: static_cast from 'Parent *' to 'Derived *', which are not
related by inheritance, is not allowed
return static_cast(p);
   ^~~~
88503.cc:2:7: note: 'Derived' is incomplete
class Derived;
  ^
88503.cc:1:7: note: 'Parent' is incomplete
class Parent;
  ^
1 error generated.

[Bug c++/52321] poor diagnostic of invalid cast

2018-12-17 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely  changed:

   What|Removed |Added

 CC||petschy at gmail dot com

--- Comment #7 from Jonathan Wakely  ---
*** Bug 88503 has been marked as a duplicate of this bug. ***

[Bug c++/52321] poor diagnostic of invalid cast

2015-03-03 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely redi at gcc dot gnu.org changed:

   What|Removed |Added

 CC||chengniansun at gmail dot com

--- Comment #6 from Jonathan Wakely redi at gcc dot gnu.org ---
*** Bug 65293 has been marked as a duplicate of this bug. ***


[Bug c++/52321] poor diagnostic of invalid cast

2012-02-22 Thread manu at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Manuel López-Ibáñez manu at gcc dot gnu.org changed:

   What|Removed |Added

 CC||manu at gcc dot gnu.org

--- Comment #5 from Manuel López-Ibáñez manu at gcc dot gnu.org 2012-02-22 
15:58:26 UTC ---
(In reply to comment #4)
 Define an enum of reasons with success first, flop the sense of the test so
 that false means coercion was OK (grep to find all calls and put a ! in 
 front
 of each), and return the reason enum instead of bool. The code that is
 reason-aware saves the enum and builds a good message; the legacy code that is
 not reason-aware treats the enum as a bool and works as before except for the
 inverted sense of the test. Maybe half an hour of work.
 
 Plausible?

Plausible in theory, sadly unrealistic in practice. But I would like to be
proven wrong, so give it a try.


[Bug c++/52321] poor diagnostic of invalid cast

2012-02-21 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

Jonathan Wakely redi at gcc dot gnu.org changed:

   What|Removed |Added

   Keywords||diagnostic
   Severity|normal  |enhancement

--- Comment #1 from Jonathan Wakely redi at gcc dot gnu.org 2012-02-21 
11:08:07 UTC ---
Comeau online gives:
ComeauTest.c, line 5: error: invalid type conversion

Clang gives:
l.cc:5:17: error: static_cast from 'foo *' to 'bar *' is not allowed

So G++ is no worse at least.

It wouldn't be as simple as just checking if the operand is a pointer/reference
to incomplete type when a static_cast fails, e.g. this fails because of casting
away const, not because the type is incomplete:

 class foo;
 int main() {
   const foo* f;
   static_castvoid*(f);
 }

There are lots of reasons a static_cast could be invalid (inaccessible bases,
virtual bases, casting away const etc. and that's just for casting Class1* to
Class2*) so if the diagnostic is improved it should cover more than just
casting from a pointer/reference to (possibly cv-qualified) incomplete type.


[Bug c++/52321] poor diagnostic of invalid cast

2012-02-21 Thread igodard at pacbell dot net
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #2 from Ivan Godard igodard at pacbell dot net 2012-02-21 
15:30:42 UTC ---
Somewhere there's an attept to coerce a to b that sees the source is a class
and the target is a class and tries to see if the source is derived from
target. That check fails because source is undefined, and the failure
propagates out as other possible casts are tried. If you save the reason for
failure your can't cast message can look at the reason. The message could
expand on other possible reasons too.

Just a suggestion - that's how we did it in the Mary compilers, and gave a list
of the plausible reasons for failure.


[Bug c++/52321] poor diagnostic of invalid cast

2012-02-21 Thread redi at gcc dot gnu.org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #3 from Jonathan Wakely redi at gcc dot gnu.org 2012-02-21 
15:53:10 UTC ---
Yep, it's build_static_cast_1 in typeck.c

But currently that has no way to store or pass back a message (just a boolean
indicating success or failure and the result of the cast) and would need a lot
of restructuring.

if (target is pointer or reference
 source is class type
 target is class type
 (target is rvalue || source is lvalue)
 target is derived from source
 can convert
 at least as qualified)

Your example fails the target is derived from source test, but that test
doesn't say it failed because the type is incomplete, it just returns false. 
And the can convert step might fail for a number of reasons, but again it
just returns a boolean.

Modifying that to report different reasons (rather than just evaluating to
'false') is not simple.


[Bug c++/52321] poor diagnostic of invalid cast

2012-02-21 Thread igodard at pacbell dot net
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52321

--- Comment #4 from Ivan Godard igodard at pacbell dot net 2012-02-21 
17:38:30 UTC ---
Define an enum of reasons with success first, flop the sense of the test so
that false means coercion was OK (grep to find all calls and put a ! in front
of each), and return the reason enum instead of bool. The code that is
reason-aware saves the enum and builds a good message; the legacy code that is
not reason-aware treats the enum as a bool and works as before except for the
inverted sense of the test. Maybe half an hour of work.

Plausible?