public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/18411] New: Warning not legitimate
@ 2004-11-09 23:23 manus at eiffel dot com
  2004-11-09 23:29 ` [Bug c/18411] " pinskia at gcc dot gnu dot org
                   ` (13 more replies)
  0 siblings, 14 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-09 23:23 UTC (permalink / raw)
  To: gcc-bugs

I'm getting the following compilation warning output:

gcc -c a.c -save-temps
a.c: In function `g':
a.c:8: warning: function called through a non-compatible type
a.c:8: note: if this code is reached, the program will abort

while compiling the following code (content of a.i):

# 1 "a.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "a.c"
extern void f();

void g(char a) {
  void * fnptr = f;

  ((void (*) (char)) fnptr) (a);

  ((void (*) (char)) f)(a);
}

It reports a warning when using `f' but not when using `fnptr'. This is rather
strange and not expected.

Why is it so?

gcc --version is:
gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)
Copyright (C) 2004 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

and was compiled on a AMD64 machine using Linux Fedora Core 3 for x86_64:
uname -a
Linux madrid.ise 2.6.9-1.667 #1 Tue Nov 2 14:50:10 EST 2004 x86_64 x86_64 
x86_64 GNU/Linux

Thanks,
Manu

-- 
           Summary: Warning not legitimate
           Product: gcc
           Version: 3.4.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: manus at eiffel dot com
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
@ 2004-11-09 23:29 ` pinskia at gcc dot gnu dot org
  2004-11-09 23:32 ` manus at eiffel dot com
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-11-09 23:29 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From pinskia at gcc dot gnu dot org  2004-11-09 23:29 -------
The warning is correct:
extern void f();

void g(void)
{
  ((void (*) (char)) f)(a);
}

this is undefined code which means we could anything at runtime (even wipe out your HD).

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
  2004-11-09 23:29 ` [Bug c/18411] " pinskia at gcc dot gnu dot org
@ 2004-11-09 23:32 ` manus at eiffel dot com
  2004-11-09 23:34 ` manus at eiffel dot com
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-09 23:32 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-09 23:32 -------
This is not undefined, I know which feature I'm calling. It is `f'. Moreover I 
provide the right function cast which matches how `f' is actually declared.

What strikes me the most is that you reject:

((void (*) (char)) f)(a);

but allow:

void * fnptr = f;
((void (*) (char)) fnptr)(a);

This is rather surprising.

Regards,
Manu

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
  2004-11-09 23:29 ` [Bug c/18411] " pinskia at gcc dot gnu dot org
  2004-11-09 23:32 ` manus at eiffel dot com
@ 2004-11-09 23:34 ` manus at eiffel dot com
  2004-11-09 23:48 ` joseph at codesourcery dot com
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-09 23:34 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-09 23:34 -------
Also one thing I forgot to add. Is that if you replace `char' by `int' then 
there is no warning at all:

extern void f();

void g(int a) {
     void * fnptr = f;

     ((void (*) (int)) fnptr) (a);  /* Ok. */

     ((void (*) (int)) f)(a);       /* Not Ok. */
}

Why `char' does trigger the warning and not `int'? This looks like a bug to
me.

Thanks,
Manu

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (2 preceding siblings ...)
  2004-11-09 23:34 ` manus at eiffel dot com
@ 2004-11-09 23:48 ` joseph at codesourcery dot com
  2004-11-09 23:51 ` pinskia at gcc dot gnu dot org
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: joseph at codesourcery dot com @ 2004-11-09 23:48 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From joseph at codesourcery dot com  2004-11-09 23:47 -------
Subject: Re:  Warning not legitimate

On Tue, 9 Nov 2004, manus at eiffel dot com wrote:

> extern void f();
> 
> void g(int a) {
>      void * fnptr = f;
> 
>      ((void (*) (int)) fnptr) (a);  /* Ok. */

If you want diagnostics for conversions between object and function 
pointers, use -pedantic.

>      ((void (*) (int)) f)(a);       /* Not Ok. */
> }
> 
> Why `char' does trigger the warning and not `int'? This looks like a bug to
> me.

The function type compatibility rules are defined in C99 6.7.5.3#15.  In 
particular:

       If one type has a parameter type list and the  other
       type  is specified by a function declarator that is not part
       of  a  function  definition  and  that  contains  an   empty
       identifier  list,  the  parameter  list  shall  not  have an
       ellipsis terminator and the type of each parameter shall  be
       compatible  with  the type that results from the application
       of the default argument  promotions.

char promotes to int under the default argument promotions, and char and 
int are not compatible, whereas int promotes to itself.



-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (3 preceding siblings ...)
  2004-11-09 23:48 ` joseph at codesourcery dot com
@ 2004-11-09 23:51 ` pinskia at gcc dot gnu dot org
  2004-11-10  0:42 ` manus at eiffel dot com
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-11-09 23:51 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From pinskia at gcc dot gnu dot org  2004-11-09 23:51 -------
As said before this is undefined code.

-- 
           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|                            |INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (4 preceding siblings ...)
  2004-11-09 23:51 ` pinskia at gcc dot gnu dot org
@ 2004-11-10  0:42 ` manus at eiffel dot com
  2004-11-10  0:48 ` pinskia at gcc dot gnu dot org
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-10  0:42 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-10 00:42 -------
Thanks for your answer. I see that following the ANSI C standard forces you to 
do something. But I believe the right thing to do is:
1 - make it a compile time error (better to catch those errors at compile time 
rather than at run-time, like I did)
2 - make it a warning and generates the code that gcc generated in the past and 
that has been working for as long as I remember.

But definitely don't do:
- produces a warning and generate code that will crash your program at run-time.

I'm definitely in favor of 2 as it would permit the code I have to continue to 
work, especially when I know that I provide all the type information to the C 
compiler so that it can generate the right code.

Hopefully someone will listen or convince me otherwise
With best regards,
Manu

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (5 preceding siblings ...)
  2004-11-10  0:42 ` manus at eiffel dot com
@ 2004-11-10  0:48 ` pinskia at gcc dot gnu dot org
  2004-11-10  0:59 ` manus at eiffel dot com
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-11-10  0:48 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From pinskia at gcc dot gnu dot org  2004-11-10 00:47 -------
We cannot do 1 as that is not allowed by the C standard (or at least a DR report of it).  Also the reason 
why this was changed was because the tree inliner was crashing on things like this if the type was float 
and the real argument was int.  The correct thing to do is do a correct prototype aka
void f(short); in the first place, other wise the code will not work anyways on some targets where int is 
passed one way and short are passed another or var args are done one way and normal arguments are 
done another way,  this does happen which is why this is undefined in the first place in C.

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (6 preceding siblings ...)
  2004-11-10  0:48 ` pinskia at gcc dot gnu dot org
@ 2004-11-10  0:59 ` manus at eiffel dot com
  2004-11-10  1:15 ` joseph at codesourcery dot com
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-10  0:59 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-10 00:59 -------
Ok, so why don't you generate the warning only when it makes sense. In my 
original case, I was passing a char and tell the C compiler it was a function 
pointer expecting a char. In this scenario it should not produce any warning.

If you have incompatible types (such as int where you expect a float/double) 
then I'm ok that you generate a warning (although I would prefer an error since 
the generated code is incorrect).

Or better, if possible, try to fix the inliner issue.

Thanks,
Manu

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (7 preceding siblings ...)
  2004-11-10  0:59 ` manus at eiffel dot com
@ 2004-11-10  1:15 ` joseph at codesourcery dot com
  2004-11-10  1:25 ` manus at eiffel dot com
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: joseph at codesourcery dot com @ 2004-11-10  1:15 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From joseph at codesourcery dot com  2004-11-10 01:15 -------
Subject: Re:  Warning not legitimate

On Wed, 10 Nov 2004, manus at eiffel dot com wrote:

> Ok, so why don't you generate the warning only when it makes sense. In my 
> original case, I was passing a char and tell the C compiler it was a function 
> pointer expecting a char. In this scenario it should not produce any warning.

There is a limit to how much we care about code with undefined behavior on 
execution.  What type you pass in the source code is a red herring; if you 
cast to a prototype type then the arguments will be getting converted to 
that type, including if you'd passed a float argument.  We aim for the 
front end to pass down type-consistent code to the rest of the compiler 
(which ideally would never need to call back into the earlier parts of the 
compiler); where the standard requires type-inconsistent code to be 
compiled but gives it execution-time undefined behavior, the only sensible 
consistent structure for the rest of the compiler involves an abort in 
place of the nonsensical code.

> If you have incompatible types (such as int where you expect a float/double) 
> then I'm ok that you generate a warning (although I would prefer an error since 
> the generated code is incorrect).

Remember DR#109:

   A conforming implementation must not fail to translate a strictly
   conforming program simply because *some* possible execution of that
   program would result in undefined behavior.

The undefined behavior is only on execution, so the program must be 
accepted.  Because its execution is nonsensical - has no meaning whatever 
- an abort is generated.



-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (8 preceding siblings ...)
  2004-11-10  1:15 ` joseph at codesourcery dot com
@ 2004-11-10  1:25 ` manus at eiffel dot com
  2004-11-10  1:26 ` pinskia at gcc dot gnu dot org
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-10  1:25 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-10 01:24 -------
I believe we do not have the right definition of unspecified behavior. Going 
back to my initial post:

extern void f();

void g(char a) {
  ((void (*) (char)) f)(a);
}

Knowing that actually `f' has been declared in some other module as:
extern void f(char){...}

Then the above code "((void (*) (char)) f)(a);" make sense. I'm simply calling 
`f' with the right type for the argument thanks to the function cast.

Could you point out where the undefined part is?

Thanks,
Manu

PS: sorry to be so picky on this issue but I feel it is important.

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (9 preceding siblings ...)
  2004-11-10  1:25 ` manus at eiffel dot com
@ 2004-11-10  1:26 ` pinskia at gcc dot gnu dot org
  2004-11-10  1:41 ` joseph at codesourcery dot com
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 15+ messages in thread
From: pinskia at gcc dot gnu dot org @ 2004-11-10  1:26 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From pinskia at gcc dot gnu dot org  2004-11-10 01:26 -------
extern void f();
really means
extern void f(...);

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (10 preceding siblings ...)
  2004-11-10  1:26 ` pinskia at gcc dot gnu dot org
@ 2004-11-10  1:41 ` joseph at codesourcery dot com
  2004-11-11 20:04 ` manus at eiffel dot com
  2005-07-04  1:38 ` SebastianR at gmx dot de
  13 siblings, 0 replies; 15+ messages in thread
From: joseph at codesourcery dot com @ 2004-11-10  1:41 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From joseph at codesourcery dot com  2004-11-10 01:41 -------
Subject: Re:  Warning not legitimate

On Wed, 10 Nov 2004, manus at eiffel dot com wrote:

> I believe we do not have the right definition of unspecified behavior. Going 

We're talking about undefined behavior (e.g. your computer, or the whole 
universe, may blow up) rather than unspecified (bounded variation on what 
may happen).


> extern void f();

> Knowing that actually `f' has been declared in some other module as:
> extern void f(char){...}

Those types are incompatible, 6.7.5.3#15, so you have undefined behavior 
by 6.2.7#2.  In that case - if the compiler can see both the declaration 
and definition in different translation units at once - it is compile-time 
undefined (a property of the program, rather than of some execution path, 
is undefined), so the program can be rejected.  But when compiling only 
the translation unit with the unprototyped declaration, it's possible that 
(a) the call through the cast pointer is never executed, (b) the real 
definition is of a compatible type e.g. void f(void) { ... } so there is 
only undefined behavior on execution, not compilation.  What is true is 
that given the first translation unit with call through a cast to an 
incompatible type, the behavior on execution of the call is guaranteed to 
be undefined if the behavior on translation wasn't already.



-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (11 preceding siblings ...)
  2004-11-10  1:41 ` joseph at codesourcery dot com
@ 2004-11-11 20:04 ` manus at eiffel dot com
  2005-07-04  1:38 ` SebastianR at gmx dot de
  13 siblings, 0 replies; 15+ messages in thread
From: manus at eiffel dot com @ 2004-11-11 20:04 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From manus at eiffel dot com  2004-11-11 20:04 -------
Sorry to come back and buzz you again. I just realized that because of this 
change in behavior of gcc you broke not just my code, but also the code of the 
people using our Eiffel compiler. Indeed our compiler generates C code that is
compiled most of the time with `gcc'. If people upgrade their `gcc' compiler to 
3.4 then the generated code compiles but does not work anymore since it will 
raise an exception.

You said that raising the exception was an acceptable solution for an undefined 
behavior per the C99 standard. However what you just did is to break existing 
code that relied on previous implementation of `gcc' (I can tell that we have 
using this scheme for more than 10 years) and thus this is something for which 
it might be good to go back to the previous code generation/behavior.

If the previous behavior made the inliner crash, then you can either fix it, or 
consider that a crash is simply a symptom of undefined behavior and therefore 
you are still compliant to the standard.

With best regards,
Manu

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [Bug c/18411] Warning not legitimate
  2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
                   ` (12 preceding siblings ...)
  2004-11-11 20:04 ` manus at eiffel dot com
@ 2005-07-04  1:38 ` SebastianR at gmx dot de
  13 siblings, 0 replies; 15+ messages in thread
From: SebastianR at gmx dot de @ 2005-07-04  1:38 UTC (permalink / raw)
  To: gcc-bugs


------- Additional Comments From SebastianR at gmx dot de  2005-07-04 01:38 -------
I think there might be an actual bug with this new warning:
In the qsort man page, it says you can use strcmp as the last argument to qsort.
So the types must be compatible, and it also works. However, this fails:

((int(*)(const void *, const void *)) strcmp) ("a", "b");

The type conversion is exactly the same, only this time it is called directly.
I think this bug/feature is really annoying, especially (as already said) the
fact that it compiles but crashes at run time.

-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18411


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2005-07-04  1:38 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-09 23:23 [Bug c/18411] New: Warning not legitimate manus at eiffel dot com
2004-11-09 23:29 ` [Bug c/18411] " pinskia at gcc dot gnu dot org
2004-11-09 23:32 ` manus at eiffel dot com
2004-11-09 23:34 ` manus at eiffel dot com
2004-11-09 23:48 ` joseph at codesourcery dot com
2004-11-09 23:51 ` pinskia at gcc dot gnu dot org
2004-11-10  0:42 ` manus at eiffel dot com
2004-11-10  0:48 ` pinskia at gcc dot gnu dot org
2004-11-10  0:59 ` manus at eiffel dot com
2004-11-10  1:15 ` joseph at codesourcery dot com
2004-11-10  1:25 ` manus at eiffel dot com
2004-11-10  1:26 ` pinskia at gcc dot gnu dot org
2004-11-10  1:41 ` joseph at codesourcery dot com
2004-11-11 20:04 ` manus at eiffel dot com
2005-07-04  1:38 ` SebastianR at gmx dot de

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).