Compile the following translation unit with 3.3: struct MDSWeight { }; void foo(int numWeights) { new MDSWeight[numWeights](); } If the compiler is configured with --enable-checking, this causes an internal compiler error: foo.cc:5: internal compiler error: tree check: expected integer_cst, have non_lvalue_expr in tree_int_cst_lt, at tree.c:3180 If the compiler is configured without checking the behavior is even less friendly: an infinite loop, with the compiler allocating more and more memory. I believe that the code above is legal. (Although admittedly it would be more natural not to write the parentheses.) The syntax of a new-expression is given in clause 5.3.4, paragraph 1. "MDSWeight[numWeights]" is a new-type-id ("MDSWeight" is a type-specifier-seq and "[numWeights]" is a direct-new-declarator. "()" is a valid new-initializer. Clause 5.3.4, paragraph 15, describes the semantics of the new-initializer, referring to clause 8.5. Nothing in 5.3.4/15 or 8.5 suggests that it's illegal to explicitly request default initialization when using array operator new. Note that the ICE is a regression from 2.95 (which accepts this construct) and from 3.1/3.2 (which reject it with an error).
Confirmed. The code is illegal: initializers are not allowed by the standard for array-new expressions. However, this is a gcc extension. I thought, this extension was abandoned recently, maybe the infinite loop is a remnant that wasn't entirely purged. W.
The infinite loop, by the way, is in build_zero_init: for (index = size_zero_node; !tree_int_cst_lt (max_index, index); index = size_binop (PLUS_EXPR, index, size_one_node)) inits = tree_cons (index, build_zero_init (TREE_TYPE (type), /*nelts=*/NULL_TREE, static_storage_p), inits); Obviously this won't work if max_index is anything other than an integer constant.
I stand corrected on my view that this code is illegal, thanks to an open eye by Matt Austern: On Tuesday 17 June 2003 07:02 pm, Matt Austern wrote: > You wrote: "The code is illegal: initializers are not allowed by the > standard for array-new > expressions." > > I'd like that to be true: it would be much easier to reject this > construct than to deal with it explicitly. However, I failed to find > an explicit statement in the standard that said so. Can you find one? Uh, Sir, if _you_ don't know then I must be wrong. I know that there used to be such an extension in gcc, and in the 3.2.3 info pages I find The use of initializer lists with new expressions has been deprecated, and is now removed from g++. I seemed to recall that this extension was about this particular case. However, if I read over the imminent section I can't find anything either. The standard is pretty vague there, talking only about single objects, not what initializers should do in the array case (presumably, if that was implied, be used for _all_ the elements). So I think I stand corrected -- sorry for spreading confusion :-( Thanks for having an open eye! W. ------------------------------------------------------------------------- Wolfgang Bangerth email: bangerth@ices.utexas.edu www: http://www.ices.utexas.edu/~bangerth/
Here's my understanding of 5.3.4/p14: an expression like "new T[n](a,b,c)" is illegal, but an expression like "new T[n]()" is legal. (The former is the gcc extension that Wolfgang was referring to.) The point is that 5.3.4/p14 explicitly distinguishes between a new-initializer of the form "()" and one that's non-empty. It prohibits the latter for array new expressions, but says nothing about the former. And just to make life a little more fun, "new T[n]" and "new T[n]()" don't always mean quite the same thing. I've confirmed my interpretation with the C++ standards committee.
And what would the difference be, between "new T[n]()" and "new T[n]"?
The main difference is that when T is a POD type, new T[n]() default-initializes the members of the array but new T[n] leaves them in an indeterminate value. Probably not an important difference most of the time.
Created attachment 4247 [details] Proposed patch, including testcases
Subject: Bug 11228 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_3-branch Changes by: austern@gcc.gnu.org 2003-06-20 00:29:26 Modified files: gcc/cp : ChangeLog init.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/expr: anew1.C anew2.C anew3.C anew4.C Log message: Fix for PR c++/11228, infinite loop for new int[n](). Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.3076.2.152&r2=1.3076.2.153 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.299.2.7&r2=1.299.2.8 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=1.2261.2.190&r2=1.2261.2.191 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew3.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew4.C.diff?cvsroot=gcc&only_with_tag=gcc-3_3-branch&r1=NONE&r2=1.1.2.1
Subject: Bug 11228 CVSROOT: /cvs/gcc Module name: gcc Changes by: austern@gcc.gnu.org 2003-06-20 00:33:58 Modified files: gcc/cp : ChangeLog init.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/expr: anew1.C anew2.C anew3.C anew4.C Log message: Fix for PR c++/11228, infinite loop for new int[n](). Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.3438&r2=1.3439 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&r1=1.323&r2=1.324 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.2780&r2=1.2781 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew1.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew2.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew3.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/anew4.C.diff?cvsroot=gcc&r1=1.1&r2=1.2
Fix for this bug checked in.
The ICE may be fixed, but this test case is now failing at runtime for me on gcc-ss-20030714 on several platforms unless I link statically. See PR c++/11309.
*** Bug 11835 has been marked as a duplicate of this bug. ***
I was interested in testing Matt Austern's Comment #6 so I wrote a little test program. I took his comment to mean that "new int[n]()" would default initialize all elements of the array to 0 and "new int[n]" would not. My test seem to show that g++ doesn't work this way. Instead, I would assume that both work like "new int[n]". Here's the program: #include <iostream> #define SZ 64000 int main() { int n; int* h1 = new int [SZ]; int* h2 = new int [SZ](); for (n = 0; n < SZ; ++n) { if (h1[n] != h2[n] || h1[n] != 0 || h2[n] != 0) { std::cout << "h1[" << n << "]=" << std::hex << h1[n] << std::dec; std::cout << ' '; std::cout << "h2[" << n << "]=" << std::hex << h2[n] << std::dec; std::cout << std::endl; } } } When I run this compiled with g++ 2.95.3 I get: h1[1528]=0 h2[1528]=5f608 h1[1530]=0 h2[1530]=3 When compiled with g++ 3.3 (the bug this report documents for 3.3 doesn't happen when 'n' is a constant instead of a variable) I get: h1[1528]=0 h2[1528]=5fb18 h1[1530]=0 h2[1530]=3 This would seem to be the opposite of what I would expect so I commented the parens out where h2 is allocated and I get the exact same results. Is there a new bug here?
Yes there is bug there but it is already filed in PR11309.