Bug 54984 - [4.6 Regression] Array allocated with new in a template class is default initialised
Summary: [4.6 Regression] Array allocated with new in a template class is default init...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.3
: P3 normal
Target Milestone: 4.7.3
Assignee: Paolo Carlini
URL:
Keywords:
: 51847 56146 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-10-19 10:42 UTC by Malcolm Parsons
Modified: 2013-01-30 10:21 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 4.4.7, 4.7.3, 4.8.0
Known to fail: 4.6.3
Last reconfirmed: 2012-10-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Malcolm Parsons 2012-10-19 10:42:39 UTC
$ cat a.cpp 
#include <stdlib.h>

struct Foo {
    Foo(size_t size) : x(new char[size]) {}
    char *x;
};

int main(int argc, char* argv[])
{
    size_t size = 1000000000;
    Foo foo(size);
    return(0);
}

$ cat b.cpp 
#include <stdlib.h>

template <class T>
struct Foo {
    Foo(size_t size) : x(new char[size]) {}
    char *x;
};

int main(int argc, char* argv[])
{
    size_t size = 1000000000;
    Foo<char> foo(size);
    return(0);
}

gcc 4.6.3 decides that the array in the templated class needs to be initialised to 0.

$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.6/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
$ g++ -O2 a.cpp -o a
$ g++ -O2 b.cpp -o b
$ time ./a

real	0m0.006s
user	0m0.000s
sys	0m0.004s
$ time ./b

real	0m4.732s
user	0m2.676s
sys	0m1.976s
$ g++ -O2 -S a.cpp
$ g++ -O2 -S b.cpp
$ diff -u a.s b.s
--- a.s	2012-10-19 11:37:35.280151921 +0100
+++ b.s	2012-10-19 11:37:13.803790575 +0100
@@ -1,10 +1,10 @@
-	.file	"a.cpp"
+	.file	"b.cpp"
 	.section	.text.startup,"ax",@progbits
 	.p2align 4,,15
 	.globl	main
 	.type	main, @function
 main:
-.LFB15:
+.LFB13:
 	.cfi_startproc
 	pushl	%ebp
 	.cfi_def_cfa_offset 8
@@ -15,13 +15,21 @@
 	subl	$16, %esp
 	movl	$1000000000, (%esp)
 	call	_Znaj
+	leal	1000000000(%eax), %edx
+	.p2align 4,,7
+	.p2align 3
+.L2:
+	movb	$0, (%eax)
+	addl	$1, %eax
+	cmpl	%edx, %eax
+	jne	.L2
 	xorl	%eax, %eax
 	leave
 	.cfi_restore 5
 	.cfi_def_cfa 4, 4
 	ret
 	.cfi_endproc
-.LFE15:
+.LFE13:
 	.size	main, .-main
 	.ident	"GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
 	.section	.note.GNU-stack,"",@progbits



gcc 4.4.3 did not initialise the array in either class.

$ g++ -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5.1' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1) 
$ g++ -O2 a.cpp -o a
$ g++ -O2 b.cpp -o b
$ time ./a

real	0m0.003s
user	0m0.004s
sys	0m0.000s
$ time ./b

real	0m0.003s
user	0m0.000s
sys	0m0.000s


I don't expect the array to be initialised unless requested by adding "()": new char[size]()
Comment 1 Jonathan Wakely 2012-10-19 12:44:32 UTC
Confirmed, it's a regression since 4.4
Comment 2 Paolo Carlini 2012-10-21 23:00:58 UTC
*** Bug 51847 has been marked as a duplicate of this bug. ***
Comment 3 Paolo Carlini 2012-10-25 23:31:05 UTC
I suspect something pretty stupid went wrong when we started using VECs. Anyway, I'm looking a bit into this.
Comment 4 Paolo Carlini 2012-10-25 23:43:30 UTC
In the broken template case, both for 'new char[size]' and 'new char[size]()', in build_raw_new_expr, init is non-NULL and VEC_empty (tree, init) is true. This can't be right.
Comment 5 Paolo Carlini 2012-10-26 00:17:45 UTC
And I'm testing the below, which appears almost obviously correct: essentially, when build_new is passed a pointer to null pointer to VEC, it should not turn the null pointer to VEC into an empty VEC!

Index: init.c
===================================================================
--- init.c      (revision 192814)
+++ init.c      (working copy)
@@ -2911,7 +2911,8 @@ build_new (VEC(tree,gc) **placement, tree type, tr
 
       orig_placement = make_tree_vector_copy (*placement);
       orig_nelts = nelts;
-      orig_init = make_tree_vector_copy (*init);
+      if (*init)
+       orig_init = make_tree_vector_copy (*init);
 
       make_args_non_dependent (*placement);
       if (nelts)
Comment 6 paolo@gcc.gnu.org 2012-10-26 14:03:38 UTC
Author: paolo
Date: Fri Oct 26 14:03:32 2012
New Revision: 192846

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=192846
Log:
/cp
2012-10-26  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54984
	* init.c (build_new): Don't turn a null *init into a pointer to
	empty vector orig_init.

/testsuite
2012-10-26  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54984
	* g++.dg/template/new11.C: New.


Added:
    trunk/gcc/testsuite/g++.dg/template/new11.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/init.c
    trunk/gcc/testsuite/ChangeLog
Comment 7 paolo@gcc.gnu.org 2012-10-26 14:19:51 UTC
Author: paolo
Date: Fri Oct 26 14:19:44 2012
New Revision: 192847

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=192847
Log:
/cp
2012-10-26  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54984
	* init.c (build_new): Don't turn a null *init into a pointer to
	empty vector orig_init.

/testsuite
2012-10-26  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54984
	* g++.dg/template/new11.C: New.

Added:
    branches/gcc-4_7-branch/gcc/testsuite/g++.dg/template/new11.C
Modified:
    branches/gcc-4_7-branch/gcc/cp/ChangeLog
    branches/gcc-4_7-branch/gcc/cp/init.c
    branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
Comment 8 Paolo Carlini 2012-10-26 14:21:15 UTC
Fixed mainline and 4.7.3.
Comment 9 Paolo Carlini 2013-01-30 10:21:55 UTC
*** Bug 56146 has been marked as a duplicate of this bug. ***