This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/15508] Size evaluation of variable-length array seem to be skipped in some cases.
- From: "takashi dot yano at nifty dot ne dot jp" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 20 May 2004 17:21:56 -0000
- Subject: [Bug c++/15508] Size evaluation of variable-length array seem to be skipped in some cases.
- References: <20040518102702.15508.takashi.yano@nifty.ne.jp>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Additional Comments From takashi dot yano at nifty dot ne dot jp 2004-05-20 17:21 -------
(In reply to comment #10)
> The comments are pretty confusing. Can we have a recap? What is exactly the
bug?
Thanks. I'd like to re-explain with some additional stuffs.
Problem:
Assertion at line 12 fails if r>=5. I have studied on assembler source code
generated by "g++ -Wall -S pr15508.cc", and found that:
The 'void func(int)' in the simple test program shown in the report needs
the size of variable length array 'int [r]' in execution. G++ 2.96 and 3.3.1
generate codes which evaluate it in 'if' block at line 9 to get address of
'a[1][0]'. The size evaluation result for 'int [r]' is needed to get pointer
'a[1]' also at line 11 and 12. The result evaluated at line 9 is reused
here. But the evaluation at line 9 is executed only when r<5. If r>=5, the
evaluation result is used in spite of being not evaluated yet. As a result,
the assertion at line 12 fails though it should always succeed. Also this
can cause segmentation fault when trying to access *a[1].
Source Code:
1: // Filename: pr15508.cc
2: #include <iostream>
3: #include <cassert>
4:
5: void func(int r)
6: {
7: int (*a)[r] = new int [2][r];
8:
9: if (r<5) a[1][0] = 0;
10:
11: std::cout << r << '\t' << a[1] - a[0] << std::endl;
12: assert( a[1] - a[0] == r);
13:
14: delete [] a;
15: }
16:
17: int main()
18: {
19: for (int i=1; i<10; i++) func(i);
20: return 0;
21: }
Reference (func() part of pr15508.s by v2.96):
.text
.align 4
.globl func__Fi
.type func__Fi,@function
func__Fi:
.LFB1:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $8, %esp
.LCFI2:
subl $12, %esp
; int (*a)[r] = new int [2][r];
movl 8(%ebp), %eax ; eax: r (read from 8(%ebp))
movl %eax, %eax
sall $3, %eax ; eax: r*2*sizeof(int) (size of 'int [2][r]')
subl $8, %eax
addl $8, %eax
pushl %eax
.LCFI3:
call __builtin_vec_new
addl $16, %esp
movl %eax, -4(%ebp) ; store address(a);
; if (r<5)
cmpl $4, 8(%ebp)
jg .L3
; Evaluating size of 'int [r]'
movl 8(%ebp), %eax ; eax: r (read from 8(%ebp))
movl %eax, %eax
sall $2, %eax ; eax: r*sizeof(int);
subl $4, %eax
addl $4, %eax
movl %eax, -8(%ebp) ; Store size of 'int [r]' to -8(%ebp)
; a[1][0] = 0;
movl -4(%ebp), %eax ; eax: address(a)
movl -8(%ebp), %edx ; edx: address offset of a[1][0]
movl $0, (%edx,%eax) ; a[1][0] = 0
.L3:
; std::cout << r << '\t' << a[1] - a[0] << std::endl;
subl $8, %esp
pushl $endl__FR7ostream
subl $12, %esp
; calculate 'a[1] - a[0]'
movl -8(%ebp), %eax ; eax: size of 'int [r]' (restore from -8(%
ebp))
addl -4(%ebp), %eax ; eax: address(a[1])
subl -4(%ebp), %eax ; eax: address(a[1]) - address(a[0])
movl %eax, %eax
sarl $2, %eax ; eax: a[1] - a[0]
pushl %eax
subl $12, %esp
pushl $9 ; '\t'
subl $12, %esp
pushl 8(%ebp) ; r
pushl $cout
.LCFI4:
call __ls__7ostreami
addl $20, %esp
movl %eax, %eax
pushl %eax
call __ls__7ostreamc
addl $20, %esp
movl %eax, %eax
pushl %eax
call __ls__7ostreami
addl $20, %esp
movl %eax, %eax
pushl %eax
.LCFI5:
call __ls__7ostreamPFR7ostream_R7ostream
addl $16, %esp
; assert( a[1] - a[0] == r);
movl -8(%ebp), %eax ; eax: size of 'int [r]' (restore from -8(%
ebp))
addl -4(%ebp), %eax ; eax: address(a[1])
subl -4(%ebp), %eax ; eax: address(a[1]) - address(a[0])
movl %eax, %eax
sarl $2, %eax ; eax: a[1] - a[0]
cmpl 8(%ebp), %eax ; compare (a[1] - [0]) and r (read from 8(%
ebp))
je .L5
pushl $__PRETTY_FUNCTION__.418
pushl $12
pushl $.LC0
pushl $.LC1
call __assert_fail
.p2align 2
.L5:
cmpl $0, -4(%ebp)
je .L8
subl $12, %esp
pushl -4(%ebp)
call __builtin_vec_delete
addl $16, %esp
.L8:
leave
ret
Additional Information:
The code below works well.
void func(int r)
{
typedef int vla[r];
vla *a = new vla [2];
if (r<5) a[1][0] = 0;
std::cout << r << '\t' << a[1] - a[0] << std::endl;
assert( a[1] - a[0] == r);
delete [] a;
}
--
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15508