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 <jwak...@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.

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" }
+}

Reply via email to