diff mbox series

PR c++/52321 print note for static_cast to/from incomplete type

Message ID 20181217153753.GA28463@redhat.com
State New
Headers show
Series PR c++/52321 print note for static_cast to/from incomplete type | expand

Commit Message

Jonathan Wakely Dec. 17, 2018, 3:37 p.m. UTC
If build_static_cast_1 returns false, and one or both type is a
pointer/reference to an incomplete class, print a note saying so. This
doesn't attempt to check whether the static_cast failed because the
type is incomplete (which was checked inside build_static_cast_1 but
not in the caller). It just informs the user that it is incomplete,
which is probably the most likely reason.

	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.

Tested powerpc64le-linux. OK for trunk?
commit c76d6fb5cfb37c2aed387def151d9f707306128a
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Dec 17 15:01:21 2018 +0000

    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.

Comments

Jason Merrill Dec. 17, 2018, 8:45 p.m. UTC | #1
On 12/17/18 10:37 AM, Jonathan Wakely wrote:
> If build_static_cast_1 returns false, and one or both type is a
> pointer/reference to an incomplete class, print a note saying so. This
> doesn't attempt to check whether the static_cast failed because the
> type is incomplete (which was checked inside build_static_cast_1 but
> not in the caller). It just informs the user that it is incomplete,
> which is probably the most likely reason.
> 
>      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.
> 
> Tested powerpc64le-linux. OK for trunk?

OK.

Jason
diff mbox series

Patch

diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index ac0c81155b5..47ddad16fc1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -7348,8 +7348,21 @@  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))
+	  && CLASS_TYPE_P (TREE_TYPE (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))
+	expr_type = TREE_TYPE (expr_type);
+      if (CLASS_TYPE_P (expr_type) && !COMPLETE_TYPE_P (expr_type))
+	inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (expr_type)),
+		"class type %qT is incomplete", expr_type);
+    }
   return error_mark_node;
 }
 
diff --git a/gcc/testsuite/g++.dg/expr/static_cast8.C b/gcc/testsuite/g++.dg/expr/static_cast8.C
new file mode 100644
index 00000000000..dc4d2162d6c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/expr/static_cast8.C
@@ -0,0 +1,27 @@ 
+// PR c++/52321
+struct A1; // { dg-message "note: class type 'A1' is incomplete" }
+struct A2; // { dg-message "note: class type 'A2' is incomplete" }
+struct B1; // { dg-message "note: class type 'B1' is incomplete" }
+struct B2; // { dg-message "note: class type 'B2' is incomplete" }
+
+struct C { };
+extern C* c;
+
+void pointers(C* c, A2* a2, B1* b1)
+{
+  (void) static_cast<A1*>(c);	// { dg-error "invalid static_cast" }
+  (void) static_cast<C*>(a2);	// { dg-error "invalid static_cast" }
+  (void) static_cast<B2*>(b1);	// { dg-error "invalid static_cast" }
+}
+
+struct D1; // { dg-message "note: class type 'D1' is incomplete" }
+struct D2; // { dg-message "note: class type 'D2' is incomplete" }
+struct E1; // { dg-message "note: class type 'E1' is incomplete" }
+struct E2; // { dg-message "note: class type 'E2' is incomplete" }
+
+void references(C& c, D2& d2, E1& e1)
+{
+  (void) static_cast<D1&>(c);	// { dg-error "invalid static_cast" }
+  (void) static_cast<C&>(d2);	// { dg-error "invalid static_cast" }
+  (void) static_cast<E2&>(e1);	// { dg-error "invalid static_cast" }
+}