]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/38233 ('map' value type + new uninitted const member warnings causes error)
authorJason Merrill <jason@redhat.com>
Fri, 28 Nov 2008 23:35:37 +0000 (18:35 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 28 Nov 2008 23:35:37 +0000 (18:35 -0500)
        PR c++/38233
        * init.c (perform_member_init): Fix value-initialization.
        (build_value_init_1): Add assert to catch cases that will break
        in the gimplifier.
        (build_default_init): Remove.
        * cp-tree.h: Remove its prototype.
        * pt.c (tsubst_expr) [DECL_EXPR]: Use build_value_init for
        value-initialization.

From-SVN: r142265

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/array25.C [new file with mode: 0644]
gcc/testsuite/g++.dg/init/value4.C [new file with mode: 0644]

index c9ce9ce44b654c86b979d2c6fb569f76cc33f31a..1c53d89ffc8e2fe61f0c9dd2618d8af0dd87d4a3 100644 (file)
@@ -1,5 +1,14 @@
 2008-11-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/38233
+       * init.c (perform_member_init): Fix value-initialization.
+       (build_value_init_1): Add assert to catch cases that will break
+       in the gimplifier.
+       (build_default_init): Remove.
+       * cp-tree.h: Remove its prototype.
+       * pt.c (tsubst_expr) [DECL_EXPR]: Use build_value_init for
+       value-initialization.
+
        PR c++/38278
        * parser.c (cp_parser_class_name): Only call 
        maybe_note_name_used_in_class if we actually found a class name.
index 9f10ed17c34d174ac7b3cf0b76b9629304436991..a03fe9bfae587634e6488a5b5758b7c992f4be93 100644 (file)
@@ -4468,7 +4468,6 @@ extern tree build_new                             (tree, tree, tree, tree, int,
                                                  tsubst_flags_t);
 extern tree build_vec_init                     (tree, tree, tree, bool, int,
                                                  tsubst_flags_t);
-extern tree build_default_init                  (tree, tree);
 extern tree build_delete                       (tree, tree,
                                                 special_function_kind,
                                                 int, int);
index 61c78e11f621ca5d662e4e7a6d6286a8ca4945e1..39d87e3669f0dcd4870782925c8e53e5a1740355 100644 (file)
@@ -266,52 +266,6 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
   return init;
 }
 
-/* Build an expression for the default-initialization of an object of
-   the indicated TYPE.  If NELTS is non-NULL, and TYPE is an
-   ARRAY_TYPE, NELTS is the number of elements in the array.  If
-   initialization of TYPE requires calling constructors, this function
-   returns NULL_TREE; the caller is responsible for arranging for the
-   constructors to be called.  */
-
-tree
-build_default_init (tree type, tree nelts)
-{
-  /* [dcl.init]:
-
-    To default-initialize an object of type T means:
-
-    --if T is a non-POD class type (clause _class_), the default construc-
-      tor  for  T is called (and the initialization is ill-formed if T has
-      no accessible default constructor);
-
-    --if T is an array type, each element is default-initialized;
-
-    --otherwise, the storage for the object is zero-initialized.
-
-    A program that calls for default-initialization of an entity of refer-
-    ence type is ill-formed.  */
-
-  /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
-     performing the initialization.  This is confusing in that some
-     non-PODs do not have TYPE_NEEDS_CONSTRUCTING set.  (For example,
-     a class with a pointer-to-data member as a non-static data member
-     does not have TYPE_NEEDS_CONSTRUCTING set.)  Therefore, we end up
-     passing non-PODs to build_zero_init below, which is contrary to
-     the semantics quoted above from [dcl.init].
-
-     It happens, however, that the behavior of the constructor the
-     standard says we should have generated would be precisely the
-     same as that obtained by calling build_zero_init below, so things
-     work out OK.  */
-  if (TYPE_NEEDS_CONSTRUCTING (type)
-      || (nelts && TREE_CODE (nelts) != INTEGER_CST))
-    return NULL_TREE;
-
-  /* At this point, TYPE is either a POD class type, an array of POD
-     classes, or something even more innocuous.  */
-  return build_zero_init (type, nelts, /*static_storage_p=*/false);
-}
-
 /* Return a suitable initializer for value-initializing an object of type
    TYPE, as described in [dcl.init].  If HAVE_CTOR is true, the initializer
    for an enclosing object is already calling the constructor for this
@@ -442,6 +396,10 @@ build_value_init_1 (tree type, bool have_ctor)
                                max_index);
 
          ce->value = build_value_init_1 (TREE_TYPE (type), have_ctor);
+
+         /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs.  */
+         gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
+                     && TREE_CODE (ce->value) != AGGR_INIT_EXPR);
        }
 
       /* Build a constructor to contain the initializations.  */
@@ -469,19 +427,13 @@ perform_member_init (tree member, tree init)
 {
   tree decl;
   tree type = TREE_TYPE (member);
-  bool is_explicit;
-
-  is_explicit = (init != NULL_TREE);
 
   /* Effective C++ rule 12 requires that all data members be
      initialized.  */
-  if (warn_ecpp && !is_explicit && TREE_CODE (type) != ARRAY_TYPE)
+  if (warn_ecpp && init == NULL_TREE && TREE_CODE (type) != ARRAY_TYPE)
     warning (OPT_Weffc__, "%J%qD should be initialized in the member initialization "
             "list", current_function_decl, member);
 
-  if (init == void_type_node)
-    init = NULL_TREE;
-
   /* Get an lvalue for the data member.  */
   decl = build_class_member_access_expr (current_class_ref, member,
                                         /*access_path=*/NULL_TREE,
@@ -490,10 +442,28 @@ perform_member_init (tree member, tree init)
   if (decl == error_mark_node)
     return;
 
+  if (init == void_type_node)
+    {
+      /* mem() means value-initialization.  */
+      if (TREE_CODE (type) == ARRAY_TYPE)
+       init = build_vec_init (decl, NULL_TREE, NULL_TREE,
+                              /*explicit_value_init_p=*/true,
+                              /* from_array=*/0,
+                              tf_warning_or_error);
+      else
+       {
+         if (TREE_CODE (type) == REFERENCE_TYPE)
+           warning (0, "%Jdefault-initialization of %q#D, "
+                    "which has reference type",
+                    current_function_decl, member);
+         init = build2 (INIT_EXPR, type, decl, build_value_init (type));
+       }
+      finish_expr_stmt (init);
+    }
   /* Deal with this here, as we will get confused if we try to call the
      assignment op for an anonymous union.  This can happen in a
      synthesized copy constructor.  */
-  if (ANON_AGGR_TYPE_P (type))
+  else if (ANON_AGGR_TYPE_P (type))
     {
       if (init)
        {
@@ -503,9 +473,8 @@ perform_member_init (tree member, tree init)
     }
   else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
-      if (is_explicit
+      if (init != NULL_TREE
          && TREE_CODE (type) == ARRAY_TYPE
-         && init != NULL_TREE
          && TREE_CHAIN (init) == NULL_TREE
          && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)
        {
@@ -532,16 +501,8 @@ perform_member_init (tree member, tree init)
     {
       if (init == NULL_TREE)
        {
-         if (is_explicit)
-           {
-             init = build_default_init (type, /*nelts=*/NULL_TREE);
-             if (TREE_CODE (type) == REFERENCE_TYPE)
-               warning (0, "%Jdefault-initialization of %q#D, "
-                        "which has reference type",
-                        current_function_decl, member);
-           }
          /* member traversal: note it leaves init NULL */
-         else if (TREE_CODE (type) == REFERENCE_TYPE)
+         if (TREE_CODE (type) == REFERENCE_TYPE)
            permerror (input_location, "%Juninitialized reference member %qD",
                       current_function_decl, member);
          else if (CP_TYPE_CONST_P (type))
index 127d37c833dd308728d4e4717eee9b3d6ba30efb..241cea6423ae525f616faed876a6e15d8947f7aa 100644 (file)
@@ -10560,8 +10560,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
                             pack expansion where the parameter packs
                             used in that expansion were of length
                             zero.  */
-                         init = build_default_init (TREE_TYPE (decl),
-                                                     NULL_TREE);
+                         init = build_value_init (TREE_TYPE (decl));
                        else
                          init = t;
                      }
index 30d4445abcf55c4942ffb5611a9414de25a09d5b..7f8786bb3ea8ea3de0425bf8b4592f4de1b5aba3 100644 (file)
@@ -1,5 +1,9 @@
 2008-11-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/38233
+       * g++.dg/init/array25.C: New test.
+       * g++.dg/init/value4.C: New test.
+
        PR c++/38278
        * g++.dg/lookup/name-clash8.C: New test.
 
diff --git a/gcc/testsuite/g++.dg/init/array25.C b/gcc/testsuite/g++.dg/init/array25.C
new file mode 100644 (file)
index 0000000..1ab2725
--- /dev/null
@@ -0,0 +1,49 @@
+// related to PR c++/38233
+// test for value-init of a member array
+// { dg-do run }
+
+struct elt 
+{
+  virtual void f();
+  char c;
+};
+
+void elt::f() { }
+
+struct foo {
+  elt buffer[500];
+  foo() ;
+  bool check () const;
+};
+
+foo::foo ()
+  : buffer()
+{}
+
+bool foo::check () const
+{
+  for (unsigned ix = sizeof (buffer)/ sizeof (buffer[0]); ix--;)
+    if (buffer[ix].c)
+      return false;
+  return true;
+}
+
+inline void *operator new (__SIZE_TYPE__ size, void *p)
+{
+  return p;
+}
+
+char heap[sizeof(elt[500])];
+
+int main ()
+{
+  for (unsigned ix = sizeof (heap); ix--;)
+    heap[ix] = ix;
+
+  foo *f = new (heap) foo ();
+  if (!f->check ())
+    return 3;
+  return 0;
+}
+
+  
diff --git a/gcc/testsuite/g++.dg/init/value4.C b/gcc/testsuite/g++.dg/init/value4.C
new file mode 100644 (file)
index 0000000..fa7a02c
--- /dev/null
@@ -0,0 +1,35 @@
+// PR c++/38233
+
+template<class _T1, class _T2>
+  struct pair
+  {
+    _T1 first;
+    _T2 second;
+
+    // _GLIBCXX_RESOLVE_LIB_DEFECTS
+    // 265.  std::pair::pair() effects overly restrictive
+    /** The default constructor creates @c first and @c second using their
+     *  respective default constructors.  */
+    pair()
+    : first(), second() { }
+};
+
+class a {
+ public:
+  a();
+};
+
+class b {
+ public:
+  // implicit default ctor
+  bool operator<(const b& rhs) const;
+
+ private:
+  a a_val;
+};
+
+typedef pair<const b, int> my_pair;
+
+void func() {
+  my_pair x;
+}