Ian Lance Taylor skrev:
Erik <sigra@xxxxxxx> writes:
From man:puts I see that it is declared "int puts(const char
*)". This means that puts does not promise to leave its argument
unchanged. Therefore the caller must push the argument anew before
each call. If it had been declared "int puts(const char * const)"
instead, the push should be moved outside the loop. Unfortunately this
does not seem to work. I tried with the following program:
void q(const unsigned int);
void f() {for (unsigned int x = 0; x != 10; x++) q(77);}
and built it with "gcc -std=c99 -Os -Wall -Wextra -Werror -S":
.L2:
subl $12, %esp
incl %ebx
pushl $77
call q
addl $16, %esp
cmpl $10, %ebx
jne .L2
As you can see, "pushl $77" is still inside the loop even though q
promises to not change its argument. This must be a bug.
This is not a bug. const on an automatic variable in C is more
advisory than anything else. You are not permitted to change a const
object, but you can cast its address to a non-const pointer.
It is a bug. If not in gcc, then in C, that allows the programmers to do
such strange things, preventing the compiler from optimizing the code.
The right thing for gcc to do would be to enable such optimizations and
warn when the code casts away constness, that it could break optimized
code. I believe that is what gcc already does for some stupidities; gcc
performs some optimizations that are broken by reinterpret_cast and
gives "warning: dereferencing type-punned pointer will break
strict-aliasing rules". So gcc should be modified to be useful for users
who need the optimization but not the bizarre misfeatures of C.
Anyway, it is surely a bug that gcc does not optimize away the "pushl
$77" inside the loop from the Ada program. Unlike C, Ada was not
designed for ugly hacks, but for clarity and for letting compilers
perform optimizations. So a promise is a promise. If a function says it
will not touch something, it won't.