Package: gcc-4.6
Version: 4.6.3-14
This bug occurs on two gcc versions I tried on Debian Wheezy 7.6 x86:
g++-4.6 (Debian 4.6.3-14) 4.6.3
g++ (Debian 4.7.2-5) 4.7.2
and one version that I tried on Debian Jessie/Sid amd64:
gcc (Debian 4.9.1-15) 4.9.1
g++ (Debian 4.9.1-15) 4.9.1
I did not try other gcc versions. I would not be surprised if this bug
is present in all gcc 4.x versions, or in all gcc versions that accept
this code.
When my test program is compiled with
$ g++ -c test.C
the generated machine code looks sensible.
When it is compiled with
$ g++ -O -c test.C
the output will be too short, and there are no references to the
external variable g. You can verify this with
$ nm test.o
00000000 T _Z12test_gcc_bugj
U _Z3fooRK1c
$ objdump -d test.o
sql/gcc-bug.o: file format elf32-i386
Disassembly of section .text:
00000000 <_Z12test_gcc_bugj>:
0: 83 ec 2c sub $0x2c,%esp
3: 8d 44 24 1c lea 0x1c(%esp),%eax
7: 89 04 24 mov %eax,(%esp)
a: e8 fc ff ff ff call b <_Z12test_gcc_bugj+0xb>
f: 83 c4 2c add $0x2c,%esp
12: c3 ret
I have prepared both C and C++ versions of this test program:
cat > test.c << EOF
struct c {
unsigned a;
};
extern struct c g;
bool foo(const struct c* d) __attribute__((pure));
inline
const struct c*
bar(unsigned f)
{
struct c d {g.a};
return f ? &d : &g;
}
bool
test_gcc_bug(unsigned f)
{
return foo(bar(f));
}
EOF
cat > test.C << EOF
class c {
public:
c(unsigned b) : a(b) {}
unsigned a;
};
extern c g;
bool foo(const c& d) __attribute__((const));
inline
const c
bar(unsigned f)
{
return f ? c(g.a) : g;
}
bool
test_gcc_bug(unsigned f)
{
return foo(bar(f));
}
EOF
When the __attribute__((pure)) or __attribute__((const)) is removed, all
code will be emitted properly.
In the C++ version, I guess it is borderline if the
__attribute__((const)) should be allowed. If the function accesses the
memory pointed to by the reference, does that count as 'global memory',
violating the 'const' attribute? If yes, then __attribute__((const))
should probably emit a warning when the function is taking references or
pointers as parameters. Anyway, incorrect code is being emitted also for
__attribute__((pure)).
This bug broke the MySQL 5.7.5 x86 build on Debian 7.6. The bug would
not manifest itself when using gcc 4.6 on that platform, but that was
only luck: gcc 4.6 would inline the problematic function call, while gcc
4.7 would inline it on this platform. The problematic code is this call
in storage/innobase/btr/btr0pcur.cc, function
btr_cur_pessimistic_insert():
if (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, n_ext),
dict_table_is_comp(index->table),
dtuple_get_n_fields(entry),
dict_table_page_size(index->table)))
The function page_zip_rec_needs_ext() corresponds to "foo" in my test
programs. It is declared as __attribute__((const)). The initialization
of the object that is returned by dict_table_page_size() was omitted.
That would be page_size_t in the MySQL source code, and "class c" or
"struct c" in my test programs above. Space for the object was allocated
from the stack, but there was no code emitted for initializing the
object before page_zip_rec_needs_ext() was invoked.
With best regards,
Marko Makela
Senior Principal Software Engineer
InnoDB Group, MySQL Server, Oracle Corporation
--
To UNSUBSCRIBE, email to debian-gcc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org
Archive: https://lists.debian.org/20141006130126.GE15621@x60s