Hi,

first blush, this is just an ICE on invalid for a quite special case. However, comparing the union case to the struct case (on which we don't ICE):

struct S
{
S s[1] = { 0 };
};

xxx.C:3:16: error: could not convert ‘0’ from ‘int’ to ‘S’
S s[1] = { 0 };

shows that in this area there is definitely room for improvement, diagnostic-wise.

The core issue turns out to be pretty straightforward: grokdeclarator doesn't check whether the element-type is incomplete. Then, uniformly calling cxx_incomplete_type_error (as *already* happens for the template version of these snippets) almost works, modulo a detail: the function doesn't tell incomplete types from types being defined. Thus I added some code for that (hopefully, a more general improvement).

Note that there are some (minor, IMHO) subtleties: for example, uniformly calling cxx_incomplete_type_error means that we don't talk anymore about *field*, thus the tweak to parse/struct-4.C.

Tested x86_64-linux.

Thanks!
Paolo.

/////////////////////////

/cp
2014-05-20  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58664
        * decl.c (grokdeclarator): Check the element type of an incomplete
        array type; call cxx_incomplete_type_error.
        * typeck2.c (cxx_incomplete_type_inform): New.
        (cxx_incomplete_type_diagnostic): Use it.

/testsuite
2014-05-20  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58664
        * g++.dg/cpp0x/nsdmi-union6.C: New.
        * g++.dg/parse/pr58664.C: Likewise.
        * g++.dg/parse/struct-4.C: Tweak.
        * g++.dg/template/error2.C: Likewise.
        * g++.dg/template/inherit8.C: Likewise.
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 210622)
+++ cp/decl.c   (working copy)
@@ -10586,11 +10586,12 @@ grokdeclarator (const cp_declarator *declarator,
          }
        else if (!staticp && !dependent_type_p (type)
                 && !COMPLETE_TYPE_P (complete_type (type))
-                && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
+                && (TREE_CODE (type) != ARRAY_TYPE
+                    || !COMPLETE_TYPE_P (TREE_TYPE (type))
+                    || initialized == 0))
          {
            if (unqualified_id)
-             error ("field %qD has incomplete type %qT",
-                    unqualified_id, type);
+             cxx_incomplete_type_error (unqualified_id, type);
            else
              error ("name %qT has incomplete type", type);
 
Index: cp/typeck2.c
===================================================================
--- cp/typeck2.c        (revision 210623)
+++ cp/typeck2.c        (working copy)
@@ -429,6 +429,25 @@ abstract_virtuals_error (abstract_class_use use, t
   return abstract_virtuals_error_sfinae (use, type, tf_warning_or_error);
 }
 
+/* Print an inform about the declaration of the incomplete type TYPE.  */
+
+static void
+cxx_incomplete_type_inform (const_tree type)
+{
+  if (current_class_type
+      && type == current_class_type
+      && TYPE_BEING_DEFINED (current_class_type))
+    inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+           "definition of %q#T is not complete until "
+           "the closing brace", type);
+  else if (!TYPE_TEMPLATE_INFO (type))
+    inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+           "forward declaration of %q#T", type);
+  else
+    inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+           "declaration of %q#T", type);
+}
+
 /* Print an error message for invalid use of an incomplete type.
    VALUE is the expression that was used (or 0 if that isn't known)
    and TYPE is the type that was invalid.  DIAG_KIND indicates the
@@ -469,14 +488,7 @@ cxx_incomplete_type_diagnostic (const_tree value,
                                      "invalid use of incomplete type %q#T",
                                      type);
       if (complained)
-       {
-         if (!TYPE_TEMPLATE_INFO (type))
-           inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
-                   "forward declaration of %q#T", type);
-         else
-           inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
-                   "declaration of %q#T", type);
-       }
+       cxx_incomplete_type_inform (type);
       break;
 
     case VOID_TYPE:
Index: testsuite/g++.dg/cpp0x/nsdmi-union6.C
===================================================================
--- testsuite/g++.dg/cpp0x/nsdmi-union6.C       (revision 0)
+++ testsuite/g++.dg/cpp0x/nsdmi-union6.C       (working copy)
@@ -0,0 +1,56 @@
+// PR c++/58664
+// { dg-do compile { target c++11 } }
+
+struct F;          // { dg-message "forward declaration" }
+
+union U            // { dg-message "not complete" }
+{
+  U u[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UT           // { dg-message "not complete" }
+{
+  UT u[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template union UT<int>;
+
+union UF
+{
+  F u[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UFT
+{
+  F u[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template union UFT<int>;
+
+struct S           // { dg-message "not complete" }
+{
+  S s[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct ST          // { dg-message "not complete" }
+{
+  ST s[1] = { 0 }; // { dg-error "incomplete type" }
+};
+
+template class ST<int>;
+
+struct SF
+{
+  F s[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct SFT
+{
+  F s[1] = { 0 };  // { dg-error "incomplete type" }
+};
+
+template class SFT<int>;
Index: testsuite/g++.dg/parse/pr58664.C
===================================================================
--- testsuite/g++.dg/parse/pr58664.C    (revision 0)
+++ testsuite/g++.dg/parse/pr58664.C    (working copy)
@@ -0,0 +1,56 @@
+// PR c++/58664
+// { dg-do compile { target c++11 } }
+
+struct F;          // { dg-message "forward declaration" }
+
+union U            // { dg-message "not complete" }
+{
+  U u;  // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UT           // { dg-message "not complete" }
+{
+  UT u;            // { dg-error "incomplete type" }
+};
+
+template union UT<int>;
+
+union UF
+{
+  F u;             // { dg-error "incomplete type" }
+};
+
+template<typename T>
+union UFT
+{
+  F u;             // { dg-error "incomplete type" }
+};
+
+template union UFT<int>;
+
+struct S           // { dg-message "not complete" }
+{
+  S s;             // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct ST          // { dg-message "not complete" }
+{
+  ST s;            // { dg-error "incomplete type" }
+};
+
+template class ST<int>;
+
+struct SF
+{
+  F s;             // { dg-error "incomplete type" }
+};
+
+template<typename T>
+struct SFT
+{
+  F s;             // { dg-error "incomplete type" }
+};
+
+template class SFT<int>;
Index: testsuite/g++.dg/parse/struct-4.C
===================================================================
--- testsuite/g++.dg/parse/struct-4.C   (revision 210624)
+++ testsuite/g++.dg/parse/struct-4.C   (working copy)
@@ -4,7 +4,7 @@
 struct A
 {
   int i;
-  struct A a; /* { dg-error "has incomplete type" } */
+  struct A a; /* { dg-error "incomplete type" } */
 };
 
 void foo()
Index: testsuite/g++.dg/template/error2.C
===================================================================
--- testsuite/g++.dg/template/error2.C  (revision 210624)
+++ testsuite/g++.dg/template/error2.C  (working copy)
@@ -7,8 +7,7 @@
 
 template<class T> struct X
 {
-  T m; // { dg-error "void" "void" }
-       // { dg-error "incomplete type" "incomplete" { target *-*-* } 10 }
+  T m; // { dg-error "incomplete type|invalid use" }
 };
 
 template<class T >
Index: testsuite/g++.dg/template/inherit8.C
===================================================================
--- testsuite/g++.dg/template/inherit8.C        (revision 210624)
+++ testsuite/g++.dg/template/inherit8.C        (working copy)
@@ -4,7 +4,7 @@ template <typename T>
 struct A
 {
   template <typename U>
-  struct B : public A <B<U> >  // { dg-message "declaration" }
+  struct B : public A <B<U> >  // { dg-message "not complete" }
   {
     struct C : public B<U>     // { dg-error "incomplete" }
     {

Reply via email to