PR c++/79118 - anon-members and constexpr
authorNathan Sidwell <nathan@acm.org>
Tue, 24 Jan 2017 19:25:32 +0000 (19:25 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 24 Jan 2017 19:25:32 +0000 (19:25 +0000)
PR c++/79118 - anon-members and constexpr
* constexpr.c (cx_check_missing_mem_inits): Caller passes type not
ctor decl.  Recursively check anonymous members.
(register_constexpr_fundef): Adjust cx_check_missing_mem_inits
call.
(explain_invalid_constexpr_fn): Likewise.

PR c++/79118
* g++.dg/cpp0x/pr79118.C: New.

From-SVN: r244881

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr79118.C [new file with mode: 0644]

index 66151e9b0a4c71cf489cd1fe05aa15747e161d8a..5b863446b8973ff950f8852bbabafd37fdb6fc0b 100644 (file)
@@ -1,3 +1,12 @@
+2017-01-24  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/79118 - anon-members and constexpr
+       * constexpr.c (cx_check_missing_mem_inits): Caller passes type not
+       ctor decl.  Recursively check anonymous members.
+       (register_constexpr_fundef): Adjust cx_check_missing_mem_inits
+       call.
+       (explain_invalid_constexpr_fn): Likewise.
+
 2017-01-23  Nathan Sidwell  <nathan@acm.org>
 
        PR c++/71710 - template using directive of field
index a3dec6884abef73ee9b9313370693ac958b8fb58..67d2428e9b6eead09cffaaae7007763a4dacab1d 100644 (file)
@@ -696,23 +696,21 @@ massage_constexpr_body (tree fun, tree body)
   return body;
 }
 
-/* FUN is a constexpr constructor with massaged body BODY.  Return true
-   if some bases/fields are uninitialized, and complain if COMPLAIN.  */
+/* CTYPE is a type constructed from BODY.  Return true if some
+   bases/fields are uninitialized, and complain if COMPLAIN.  */
 
 static bool
-cx_check_missing_mem_inits (tree fun, tree body, bool complain)
+cx_check_missing_mem_inits (tree ctype, tree body, bool complain)
 {
-  bool bad;
-  tree field;
-  unsigned i, nelts;
-  tree ctype;
-
-  if (TREE_CODE (body) != CONSTRUCTOR)
-    return false;
-
-  nelts = CONSTRUCTOR_NELTS (body);
-  ctype = DECL_CONTEXT (fun);
-  field = TYPE_FIELDS (ctype);
+  unsigned nelts = 0;
+  
+  if (body)
+    {
+      if (TREE_CODE (body) != CONSTRUCTOR)
+       return false;
+      nelts = CONSTRUCTOR_NELTS (body);
+    }
+  tree field = TYPE_FIELDS (ctype);
 
   if (TREE_CODE (ctype) == UNION_TYPE)
     {
@@ -726,13 +724,13 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
       return false;
     }
 
-  bad = false;
-  for (i = 0; i <= nelts; ++i)
+  /* Iterate over the CONSTRUCTOR, checking any missing fields don't
+     need an explicit initialization.  */
+  bool bad = false;
+  for (unsigned i = 0; i <= nelts; ++i)
     {
-      tree index;
-      if (i == nelts)
-       index = NULL_TREE;
-      else
+      tree index = NULL_TREE;
+      if (i < nelts)
        {
          index = CONSTRUCTOR_ELT (body, i)->index;
          /* Skip base and vtable inits.  */
@@ -740,13 +738,25 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
              || DECL_ARTIFICIAL (index))
            continue;
        }
+
       for (; field != index; field = DECL_CHAIN (field))
        {
          tree ftype;
-         if (TREE_CODE (field) != FIELD_DECL
-             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
-             || DECL_ARTIFICIAL (field))
+         if (TREE_CODE (field) != FIELD_DECL)
+           continue;
+         if (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
            continue;
+         if (DECL_ARTIFICIAL (field))
+           continue;
+         if (ANON_AGGR_TYPE_P (TREE_TYPE (field)))
+           {
+             /* Recurse to check the anonummous aggregate member.  */
+             bad |= cx_check_missing_mem_inits
+               (TREE_TYPE (field), NULL_TREE, complain);
+             if (bad && !complain)
+               return true;
+             continue;
+           }
          ftype = strip_array_types (TREE_TYPE (field));
          if (type_has_constexpr_default_constructor (ftype))
            {
@@ -766,6 +776,15 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain)
        }
       if (field == NULL_TREE)
        break;
+
+      if (ANON_AGGR_TYPE_P (TREE_TYPE (index)))
+       {
+         /* Check the anonymous aggregate initializer is valid.  */
+         bad |= cx_check_missing_mem_inits
+           (TREE_TYPE (index), CONSTRUCTOR_ELT (body, i)->value, complain);
+         if (bad && !complain)
+           return true;
+       }
       field = DECL_CHAIN (field);
     }
 
@@ -803,7 +822,8 @@ register_constexpr_fundef (tree fun, tree body)
     }
 
   if (DECL_CONSTRUCTOR_P (fun)
-      && cx_check_missing_mem_inits (fun, massaged, !DECL_GENERATED_P (fun)))
+      && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
+                                    massaged, !DECL_GENERATED_P (fun)))
     return NULL;
 
   /* Create the constexpr function table if necessary.  */
@@ -864,7 +884,7 @@ explain_invalid_constexpr_fn (tree fun)
          body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
          require_potential_rvalue_constant_expression (body);
          if (DECL_CONSTRUCTOR_P (fun))
-           cx_check_missing_mem_inits (fun, body, true);
+           cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
        }
     }
   input_location = save_loc;
index e70200bac577e34e9b8323e601c379520cc210bf..cdd4e1b8a0482e113936bed3ac20b8bb4b8e405e 100644 (file)
@@ -1,3 +1,8 @@
+2017-01-24  Nathan Sidwell  <nathan@acm.org>
+
+       PR c++/79118
+       * g++.dg/cpp0x/pr79118.C: New.
+
 2017-01-24  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gcc.target/arm/vfp-longcall-apcs.c: New test.
 
 2017-01-20  Nathan Sidwell  <nathan@acm.org>
 
-       PR c++/79495
+       PR c++/78495
        * g++.dg/cpp1z/inh-ctor38.C: New.
 
 2017-01-20  Marek Polacek  <polacek@redhat.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr79118.C b/gcc/testsuite/g++.dg/cpp0x/pr79118.C
new file mode 100644 (file)
index 0000000..e7dfeb3
--- /dev/null
@@ -0,0 +1,42 @@
+// { dg-do compile { target c++11 } }
+// { dg-additional-options { -Wno-pedantic } }
+// PR c++/79118 failure to check initialization of anonymous members.
+
+struct One
+{
+  union
+  {
+    int a;
+    int b;
+  };
+
+  constexpr One () : a(), b() {} // { dg-error "multiple" }
+  constexpr One (int) : a() {}
+  constexpr One (unsigned) : b () {}
+  constexpr One (void *) {} // { dg-error "exactly one" }
+};
+
+One a ();
+One b (0);
+One c (0u);
+One d ((void *)0);
+
+struct Two
+{
+  struct
+  {
+    int a;
+    int b;
+  };
+
+  constexpr Two () : a(), b() {}
+  constexpr Two (int) : a() {} // { dg-error "b' must be initialized" }
+  constexpr Two (unsigned) : b () {} // { dg-error "a' must be initialized" }
+  constexpr Two (void *) {} // { dg-error "a' must be initialized" }
+   // { dg-error "b' must be initialized" "" { target *-*-* } 35 }
+};
+
+Two e ();
+Two f (0);
+Two g (0u);
+Two h ((void *)0);