Date: Tue, 16 Apr 2013 15:13:55 +0200 From: keramida@ceid.upatras.gr (Giorgos Keramidas) To: Bruce Evans <brde@optusnet.com.au> Cc: svn-src-head@FreeBSD.org, Gregory Shapiro <gshapiro@FreeBSD.org>, src-committers@FreeBSD.org, Dimitry Andric <dim@FreeBSD.org>, svn-src-all@FreeBSD.org Subject: Re: svn commit: r246880 - in head: lib/libsm libexec/mail.local libexec/smrsh share/mk usr.bin/vacation usr.sbin/sendmail Message-ID: <87zjwy62jw.fsf@saturn.laptop> In-Reply-To: <20130416205349.W1783@besplex.bde.org> (Bruce Evans's message of "Tue, 16 Apr 2013 21:28:36 %2B1000 (EST)") References: <201302162017.r1GKHVdY022667@svn.freebsd.org> <87a9ozayzk.fsf@saturn.laptop> <516D13C5.70900@FreeBSD.org> <20130416205349.W1783@besplex.bde.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 16 Apr 2013 21:28:36 +1000 (EST), Bruce Evans <brde@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@gmail.com
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?87zjwy62jw.fsf>