Bug 33916 - [4.2 Regression] Default constructor fails to initialize array members
Summary: [4.2 Regression] Default constructor fails to initialize array members
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.2.2
: P1 normal
Target Milestone: 4.2.4
Assignee: Jason Merrill
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-10-26 21:05 UTC by Michael Elizabeth Chastain
Modified: 2022-05-19 16:39 UTC (History)
10 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work: 4.3.0
Known to fail:
Last reconfirmed: 2008-01-02 23:32:42


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Elizabeth Chastain 2007-10-26 21:05:52 UTC
(This may be related to PR 30111 )

In this program, a default constructor fails to initialize the given array members to zero.  Results are shown with several versions of gcc.

===

#include <string.h>
#include <iostream>

namespace {

class Stats {
  friend void alpha();
  private:
    int a_[12];
    int b_[12];
};

void dirty_stack() {
  char array[4096];
  memset(array, 0x11, 4096);
}

void alpha() {
  Stats my_stats = Stats();
  for (int i = 0; i < 12; ++i) {
    std::cout << my_stats.a_[i] << " ";
  }
  std::cout << std::endl;
}

}

int main() {
  dirty_stack();
  alpha();
  return 0;
}

===

mec@hollerith:~/exp-array-default$ /home/mec/gcc-4.1.2/install/bin/g++ z3.cc && ./a.out
0 0 0 0 0 0 0 0 0 0 0 0 

mec@hollerith:~/exp-array-default$ /home/mec/gcc-4.2.2/install/bin/g++ z3.cc && ./a.out
286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 

mec@hollerith:~/exp-array-default$ /home/mec/gcc-4.3-20071019/install/bin/g++ z3.cc && ./a.out
286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153 286331153
Comment 1 Lawrence Crowl 2007-10-31 20:08:12 UTC
The wording in the C++ standard working paper is as follows:

8.5 Initializers [dcl.init]

-8- An object whose initializer is an empty set of parentheses, i.e.,
   (), shall be value-initialized.

Therefore, in <<< Stats my_stats = Stats(); >>>, the temporary object
is value-initialized and then my_stats is copy-constructed.

-5- To value-initialize an object of type T means:
   -- if T is a non-union class type without a user-provided
      constructor, then every non-static data member and base-class
      component of T is value-initialized;93)

   93) Value-initialization for such a class object may be
       implemented by zero-initializing the object and then calling
       the default constructor.

   -- if T is an array type, then each element is value-initialized;

   -- otherwise, the object is zero-initialized

Therefore, the temporary should be zero-initialized and the resulting
copy should copy zeros.  So, I conclude that gcc 4.2.1 is in error.
(I suspect the compiler already eliminates the copy.)

I suspect the problem arose in someone thinking that the zero
initialization in front of a call to a default constructor was
redundant.  Alas, it is not.  It is redundant only if the constructor
initializes all fields, which is generally unknowable, though the
compiler could determine so for many types and constructors.
Comment 2 Gabriel Dos Reis 2007-11-01 02:16:55 UTC
I concur with Lawrence' analysis.
I was bitten by this bug myself in my own code.
Comment 3 Janis Johnson 2007-12-11 00:03:53 UTC
A regression hunt on powerpc-linux identified this patch:

    http://gcc.gnu.org/viewcvs?view=rev&rev=117834

    r117834 | mmitchel | 2006-10-17 22:35:29 +0000 (Tue, 17 Oct 2006)
Comment 4 Mark Mitchell 2008-01-07 18:13:51 UTC
I still agree that we should fix this -- but it is worth noting that value-initialization did not exist in C++98.  I believe that the current G++ behavior conforms to the original C++98 specification.

Does anyone know if this change was in C++98 TC1?  Or not until C++0x?
Comment 5 Lawrence Crowl 2008-01-07 18:58:09 UTC
Subject: Re:  [4.2/4.3 Regression] Default constructor fails to initialize array members

Value initialization was in C++98 TC1 (2003) as a result of core issue 178.

Comment 6 Steven Bosscher 2008-01-22 21:01:12 UTC
There is some discussion about this bug in the following thread on gcc-patches:
http://gcc.gnu.org/ml/gcc-patches/2008-01/msg00326.html
Comment 7 Richard Biener 2008-01-25 15:46:36 UTC
Jason, can you coordinate with Mark and help with the remaining P1 C++ regressions?
Comment 8 Joseph S. Myers 2008-02-01 16:55:01 UTC
4.2.3 is being released now, changing milestones of open bugs to 4.2.4.
Comment 9 Jason Merrill 2008-02-04 03:29:41 UTC
Subject: Bug 33916

Author: jason
Date: Mon Feb  4 03:28:53 2008
New Revision: 132088

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=132088
Log:
        PR c++/33916
        * cp/init.c (build_value_init_1): New function.
        (build_value_init): New function.
        * cp/typeck2.c (build_functional_cast): Call it.
        * cp/cp-gimplify.c (cp_gimplify_init_expr): Handle its output.

        * cp/cp-tree.h (TYPE_HAS_USER_CONSTRUCTOR): Rename from
        TYPE_HAS_CONSTRUCTOR.
        * cp/class.c (finish_struct_bits, maybe_warn_about_overly_private_class,
        add_implicitly_declared_members): Adjust.
        (check_field_decls): Adjust. Remove warnings about reference/const
        in class without constructor.
        (check_bases_and_members): Adjust.  Give those warnings here instead.
        * cp/decl.c (fixup_anonymous_aggr): Adjust.
        (check_initializer): Adjust, clarify logic slightly.
        (grok_special_member_properties): Adjust, only set if user-provided.
        * cp/rtti.c (create_tinfo_types): Don't set.
        * cp/cvt.c (ocp_convert): Remove exception for vtable_entry_type et al.
        Use same_type_ignoring_top_level_qualifiers_p.
        * cp/pt.c (check_explicit_specialization): Adjust.
        (instantiate_class_template): Adjust.

        * print-tree.c (print_node) [CONSTRUCTOR]: Print elements.

Added:
    trunk/gcc/testsuite/g++.dg/init/value1.C
    trunk/gcc/testsuite/g++.dg/warn/Wextra-1.C
    trunk/gcc/testsuite/g++.dg/warn/Wextra-2.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/class.c
    trunk/gcc/cp/cp-gimplify.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/cvt.c
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/init.c
    trunk/gcc/cp/pt.c
    trunk/gcc/cp/rtti.c
    trunk/gcc/cp/typeck2.c
    trunk/gcc/print-tree.c
    trunk/gcc/testsuite/g++.dg/init/ctor8.C

Comment 10 Richard Biener 2008-02-04 12:15:03 UTC
Fixed on the trunk.
Comment 11 Jason Merrill 2008-02-12 06:38:20 UTC
Subject: Bug 33916

Author: jason
Date: Tue Feb 12 06:37:34 2008
New Revision: 132254

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=132254
Log:
        PR c++/34094
        * decl2.c (cp_write_global_declarations): Don't write out static
        data members with DECL_IN_AGGR_P set.

        PR c++/33916
        * Revert:
        2006-10-17  Mark Mitchell  <mark@codesourcery.com>
        PR c++/29039
        * typeck2.c (build_functional_cast): Don't zero-initialize
        non-PODs; instead, call their constructors.

Removed:
    branches/gcc-4_2-branch/gcc/testsuite/g++.dg/init/ctor8.C
Modified:
    branches/gcc-4_2-branch/gcc/cp/ChangeLog
    branches/gcc-4_2-branch/gcc/cp/decl2.c
    branches/gcc-4_2-branch/gcc/cp/typeck2.c
    branches/gcc-4_2-branch/gcc/testsuite/ChangeLog

Comment 12 Jason Merrill 2008-02-12 06:41:16 UTC
Fixed for 4.2.4 by reverting part of Mark's patch for PR 29039.
Comment 13 Jackie Rosen 2014-02-16 13:12:37 UTC Comment hidden (spam)