Q.: inconsistent (?) warnings about functions called through non-compatible types

2015-03-29 Thread Godmar Back
Hi,

why does gcc (4.4.7 and 4.8.2) sometimes warn and sometimes not warn
when undefined behavior is invoked when making illegal function
pointer conversions?

For instance, consider the code below:

-
/* Tested with gcc 4.4.7 and 4.8.2 */
#include 
#include 

bool boolFunctionThatReturnsFalse() { return false; }

typedef int (*intFunction)(void);

int
main()
{
/* no warning here, just undefined behavior */
intFunction f = (intFunction) boolFunctionThatReturnsFalse;
if ( f() )
printf("true\n");
else
printf("false\n");

/* gcc warns and emits abort code */
if ( ((intFunction) boolFunctionThatReturnsFalse) () )
printf("true\n");
else
printf("false\n");
}

---

Why does assigning boolFunctionThatReturnsFalse to a variable f after
the cast, instead of directly dereferencing it, silence the compiler's
warnings?

Thanks.

 - Godmar

ps: I would like to see the warning, of course, since casting a bool
returning function to an int returning function is undefined behavior.


Re: Q.: inconsistent (?) warnings about functions called through non-compatible types

2015-03-29 Thread Godmar Back
On Sun, Mar 29, 2015 at 3:26 PM, Andreas Schwab  wrote:
> Godmar Back  writes:
>
>> ps: I would like to see the warning, of course, since casting a bool
>> returning function to an int returning function is undefined behavior.
>
> The cast itself is ok, the undefined behavior only occurs when calling
> it without casting back.
>

Thanks. I'm a bit confused then what constitutes defined & undefined behavior.

The actual situation I encountered is best described by this example:

--
/* Tested with gcc 4.4.7 and 4.8.2 -m32 */
#include 
#include 

bool boolFunctionThatReturnsFalse() {
// I'm faking this here, but a real 'bool' function could
// place 0x100 in $eax when meaning to return false.
register bool r asm("%eax");
asm("mov $0x100, %eax");
return r;
}

typedef int (*intFunction)(void);

int
main()
{
if ( boolFunctionThatReturnsFalse() )
printf("true\n");
else
printf("false\n");

intFunction f = (intFunction) boolFunctionThatReturnsFalse;
if ( f() )
printf("true\n");
else
printf("false\n");
}
--

(I'm faking the return value of boolFunctionThatReturnsFalse here, but
I have observed this behavior in actual code.)

Is this defined or undefined behavior that my problem invokes?

 - Godmar


question about -mpush-args -maccumulate-outgoing-args on gcc for x86

2009-09-01 Thread Godmar Back
Hi,

I'm using gcc version 4.1.2 20080704 (Red Hat 4.1.2-44) for a x86
target. The info page says:

`-mpush-args'
`-mno-push-args'
 Use PUSH operations to store outgoing parameters.  This method is
 shorter and usually equally fast as method using SUB/MOV
 operations and is enabled by default.  In some cases disabling it
 may improve performance because of improved scheduling and reduced
 dependencies.

`-maccumulate-outgoing-args'
 If enabled, the maximum amount of space required for outgoing
 arguments will be computed in the function prologue.  This is
 faster on most modern CPUs because of reduced dependencies,
 improved scheduling and reduced stack usage when preferred stack
 boundary is not equal to 2.  The drawback is a notable increase in
 code size.  This switch implies `-mno-push-args'.

This information is also found on
http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86_002d64-Options.html


Is this information up-to-date?

It appears to me that '-mno-push-args' is the enabled by default (*),
and not '-mpush-args'.  Moreover, since -maccumulate-outgoing-args
implies -mno-push-args, it appears that the only way to obtain
'push-args' behavior is to specify '-mno-accumulate-outgoing-args' - a
switch which the documentation doesn't even mention.

I have searched the mailing list archives and the only post I found
was this one:
http://gcc.gnu.org/ml/gcc/2005-01/msg00761.html which is at odds with
the documentation above.

Thanks.

 - Godmar

(*) for instance, see:

gb...@setzer [39](~/tmp) > cat call.c
void caller(void) {
extern void callee(int);
callee(5);
}
gb...@setzer [40](~/tmp) > gcc -mno-push-args -S call.c
gb...@setzer [41](~/tmp) > cat call.s
.file   "call.c"
.text
.globl caller
.type   caller, @function
caller:
pushl   %ebp
movl%esp, %ebp
subl$8, %esp
movl$5, (%esp)
callcallee
leave
ret
.size   caller, .-caller
.ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section.note.GNU-stack,"",@progbits


Re: question about -mpush-args -maccumulate-outgoing-args on gcc for x86

2009-09-01 Thread Godmar Back
Minor correction to my previous email:

On Tue, Sep 1, 2009 at 10:08 AM, Godmar Back wrote:
>
> gb...@setzer [39](~/tmp) > cat call.c
> void caller(void) {
>    extern void callee(int);
>    callee(5);
> }

This:

> gb...@setzer [40](~/tmp) > gcc -mno-push-args -S call.c

should be '-mpush-args' as in:

gb...@cyan [4](~/tmp) > gcc -S -mpush-args call.c
gb...@cyan [5](~/tmp) > cat call.s
.file   "call.c"
.text
.globl caller
.type   caller, @function
caller:
pushl   %ebp
movl%esp, %ebp
subl$8, %esp
movl$5, (%esp)
callcallee
leave
ret
.size   caller, .-caller
.ident  "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-44)"
.section.note.GNU-stack,"",@progbits

The point here is that '-mpush-args' is ineffective unless
'-mno-accumulate-outgoing-args' is given, and that the documentation,
in my opinion, may be misleading by

a) not mentioning the -mno-accumulate-outgoing-args switch

b) saying that '-mpush-args' is the default when it's an ineffective
default (since the default -maccumulate-outgoing-args appears to
override it)

c) not mentioning that -maccumulate-outgoing-args is the default - in
fact, the discussion in the section of push-args/no-push-args appears
to imply that it shouldn't be the default.

Thanks.

 - Godmar


Re: question about -mpush-args -maccumulate-outgoing-args on gcc for x86

2009-09-01 Thread Godmar Back
On Tue, Sep 1, 2009 at 12:31 PM, Ian Lance Taylor wrote:
> Godmar Back  writes:
>
>> It appears to me that '-mno-push-args' is the enabled by default (*),
>> and not '-mpush-args'.
>
> The default varies by processor--it dependson the -mtune option.

I don't know how to find out which tuning is enabled by default; I
assume -mtune=generic?
Would statements with respect to what "default" is apply to the
"default" mtune setting?

>
>> Moreover, since -maccumulate-outgoing-args
>> implies -mno-push-args, it appears that the only way to obtain
>> 'push-args' behavior is to specify '-mno-accumulate-outgoing-args' - a
>> switch which the documentation doesn't even mention.
>
> That is likely true.
>
> If you want to send a patch for the docs, that would be great.
>

Whilst in general I am not opposed to this, and have contributed to
many open source projects in the past, I feel that the documentation
should be updated by someone who can actually vouch for the
completeness and accuracy of what's written, which I definitely
cannot. I also cannot verify the accuracy of the claims with respect
to speeds of the two options. Moreover, these claims are made in a
section of the documentation that applies to an entire architecture
rather than a specific processor implementation. Perhaps they should
simply be removed?

I'm also uncertain where exactly the difference between
accumulate-outgoing-args and push-args is.
accumulate implies no-push-arg, and no-accumulate+push-arg is the
traditional approach, but what does no-accumulate+no+push+arg look
like and does it even make sense?

It would also be great if '-mpush-args' without
-mno-accumulate-outgoing-args would trigger a warning:
Warning: -mpush-args ignored while -maccumulate-outgoing-args is in effect.

 - Godmar


rationale for eliding modifications to string constants

2010-09-14 Thread Godmar Back
Hi,

this may be a FAQ - in my class today when discussing how gcc
generates code for x86, I was stumped when I showed an example of how
gcc handles attempts to modify (read-only) string literals/constants.
(I'm sending this to gcc rather than gcc-help because I'm asking for a
design rationale - I believe I understand the semantics of string
constants in C. If in appropriate, I'm happy to resend there.)

Specifically, I was surprised to see that gcc 4.1.2, when invoked with
-O, simply elided the offending statement s[0] = 'H' in the example
below.

int
main()
{
    char * s = (char *)"hello";     // read-only
    printf("%s\n", s);
    s[0] = 'H';    // gcc -O elides this
    printf("%s\n", s);
    return 0;
}

Could someone briefly provide justification/rationale for this decision?

Is the rationale simply that since "the behavior of a program that
attempts to modify a string constant is undefined" (K&R) you felt
justified in silently discarding it (rather than letting it proceed or
cause a runtime error if the string literal is mapped in a read-only
section of the address space?)

I note that even though the compiler knows it is taking advantage of a
rule that allows it to produce code that contains undefined behavior,
there appears to be no warning option to alert the user. Notably, gcc
-Wall -Wwrite-string is silent for the above program.

Thanks.

 - Godmar


Re: rationale for eliding modifications to string constants

2010-09-14 Thread Godmar Back
On Tue, Sep 14, 2010 at 2:35 PM, Ian Lance Taylor  wrote:
>
> I think this is simply a bug.  It doesn't happen with current gcc.  With
> gcc 4.4.3 the assignment is being eliminated because it is considered to
> be dead code.
>
> I agree that it is an error for gcc to simply eliminate this assignment
> with no warning.
>

Thanks, that's what I thought.

 - Godmar