svn commit: r246880 - in head: lib/libsm libexec/mail.local libexec/smrsh share/mk usr.bin/vacation usr.sbin/sendmail
Giorgos Keramidas
keramida at ceid.upatras.gr
Tue Apr 16 13:14:19 UTC 2013
On Tue, 16 Apr 2013 21:28:36 +1000 (EST), Bruce Evans <brde at optusnet.com.au> wrote:
>On Tue, 16 Apr 2013, Dimitry Andric wrote:
>> Have you tried the patch I posted here?
>>
>> http://lists.freebsd.org/pipermail/freebsd-current/2013-March/040634.html
>>
>> If people feel this is the right approach, I am happy to commit it. If
>> people prefer to just shut up warnings, I am happy with that too.
Hi Dimitry,
I haven't but I will right now. Thanks for pointing me to it :)
Also Bruce, thanks for the very detailed explanation. I admit I was a
bit confused when a similar small test program I wrote failed to trigger
the warning in clang:
#include <stdio.h>
void foo(int code, const char *text);
void
foo(code, text)
int code;
const char *text;
{
printf("error %d: %s", code, text);
}
int
main(void)
{
foo(0, "unknown error");
return 0;
}
But now -- having read all the details you wrote -- using stdbool.h and
changing the type of 'code' to bool, *does* trigger the promotion and
the warning:
#include <stdbool.h>
#include <stdio.h>
void foo(bool code, const char *text);
void
foo(code, text)
bool code;
const char *text;
{
if (code != false)
printf("error: %s", text);
}
int
main(void)
{
foo(false, "unknown error");
return 0;
}
% cc -O2 -pipe -std=gnu99 -Qunused-arguments -fstack-protector -c
proto.c
proto.c:8:10: warning: promoted type 'int' of K&R function parameter is
not compatible with the parameter type 'bool' declared in a previous
prototype
[-Wknr-promoted-parameter]
bool code;
^
proto.c:4:15: note: previous declaration is here
void foo(bool code, const char *text);
^
1 warning generated.
> stdbool is certainly incompatible with simple use of __P(()), but why does
> the error message say that the function type is 'void ()', and why doesn't
> it say that the prototype doesn't match the function? The function is
> declared as:
>
> @ static void getsasldata __P((char *, bool, MAILER *, MCI *, ENVELOPE *));
>
> This says that the function type is the same as the parameter type.
>
> @ static void
> @ getsasldata(line, firstline, m, mci, e)
> @ char *line;
> @ bool firstline;
> @ MAILER *m;
> @ register MCI *mci;
> @ ENVELOPE *e;
> @ {
>
> This says that the function type is different from what the function's
> prototype is, at least if the bool is smaller than int or otherwise
> magic, which it is on at least amd64.
>
> clang prints a good error message in the following simplified example:
>
> @ #include <stdbool.h>
> @ @ void foo(bool first);
> @ @ void
> @ foo(first)
> @ bool first;
> @ {
> @ }
>
> @ z.c:7:7: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'bool' declared in a previous prototype [-Wknr-promoted-parameter]
> @ bool first;
> @ ^
> @ z.c:3:15: note: previous declaration is here
> @ void foo(bool first);
> @ ^
> @ 1 warning generated.
>
> This happens with plain cc -c.
>
> gcc of course turns the undefined behaviour from this into a portability
> problem by accepting the bad code. It takes gcc -pedantic to get a warning.
>
> The correct prototype on amd64 is 'void foo(int first);'. This is MD.
> Unfortunately, the correct way to declare this is unsupported AFAIK. It
> is 'void foo(__promoteof(bool) first);'. __P(()) is really hard to use,
> since to use it you first have to modify compilers to support
> __promoteof(), then use it on the type of all integer args whose type is
> not int or larger, or do this using MD ifdefs.
>
> Extending the example a little gives the answer to my question:
>
> @ #include <stdbool.h>
> @ @ typedef void vb(bool first);
> @ @ vb foo;
> @ void bar(vb *p);
> @ @ void
> @ foo(first)
> @ bool first;
> @ {
> @ bar(foo);
> @ }
>
> @ z.c:10:7: warning: promoted type 'int' of K&R function parameter is not compatible with the parameter type 'bool' declared in a previous prototype [-Wknr-promoted-parameter]
> @ bool first;
> @ ^
> @ z.c:5:4: note: previous declaration is here
> @ vb foo;
> @ ^
> @ z.c:12:6: warning: incompatible pointer types passing 'void ()' to parameter of type 'vb *' (aka 'void (*)(bool)') [-Wincompatible-pointer-types]
> @ bar(foo);
> @ ^~~
> @ z.c:6:14: note: passing argument to parameter 'p' here
> @ void bar(vb *p);
> @ ^
> @ 2 warnings generated.
>
> Apparently clang ignores the mismatched prototype after printing a warning
> about it, and also throws away the type info that it learns by compiling
> the K&R function, so it is left with only 'void ()' for the type. Then
> the warnings for some reason emphasize the secondary warnings from this.
>
> The first warning should be an error. It is only a warning for gcc -pedantic
> too.
>
> Bruce
--
Giorgos Keramidas; gkeramidas at gmail.com
More information about the svn-src-all
mailing list