svn commit: r281517 - head/usr.bin/ipcs
Bruce Evans
brde at optusnet.com.au
Tue Apr 14 07:11:00 UTC 2015
On Tue, 14 Apr 2015, Eitan Adler wrote:
> Log:
> ipcs: fix builds that use gcc
> gcc gets annoyed by duplicate declarations
You mean "Fix builds that use a working compiler. Working compilers
report redundant declarations when requested to do so by the
-Wredundant-decls flag which I recently enabled by raising WARNS to
6."
clang apparently silently ignores the request.
gcc48 still has the following bugs in -Wredundant-decls:
- it redundantly says that redundant declarations are redeclarations.
Only a very magic type or variable could redundant if it is only
declared once by the program (including in headers included by
the program). Perhaps some predefined type or variable is magic
enough. But then the warning should be different. E.g., main()
and exit() are known to the compiler except in freestanding
environments.
gcc already has special handling for main(), to allow it to be
declared as either "int main(void);" or "int main(int argc, char
**argv);", as required to allow the program to use either of
these. Declaring one of these in either <stdlib.h> or a compiler
predeclaration would break use of the other one unless the first
declaration is magic. I think gcc skips the warning for its
builtin predeclaration but wouldn't skip if for a declaration in
a header. I think standards don't allow main() to be declared in
any standard header since they don't require compilers to have
magic to support this.
exit() is simpler since it has only 1 correct declaration in
hosted environments. It should have a predeclaration in the
compiler and another one in <stdlib.h>. The one in <stdlib.h>
is redundant, but the compiler must not warn about it. The
compiler should warn about it for any declaration of it outside
of standard headers. The correct practice is to include
<stdlib.h> to get the declaration. That gives at least a
doubly-redundant declaration if the application declares it
again, and no magic is needed to get the warning. If the
application doesn't include <stdlib.h>, then the warning
should change to one about improper practice when certain
warnings are enabled. I think gcc only warns about inconsistent
uses and the C standard only requires this. So you should
be able to non-redundantly declare exit() iff you are careful
to not include <stdlib.h> and use the same declaration as
<stdlib.h>.
- it incorrectly says that non-redundant non-redeclarations are
redundant redeclarations. C allows building up types by
supplying additional information in each step. E.g.:
void myfunc();
void myfunc(int);
gcc48 still warns that the second declaration is a redundant
redeclaration when it is actually a non-redundant non-redeclaration.
The first declaration is redundant in some cases (especially
when there is nothing between the declarations. Nested incomplete
function declarations allow arbitrarily long chains of
non-redundant non-redeclarations to build up a single top-level
declaration:
typedef void ifv(); /* incomplete type for func returning void */
typedef void cfv(int); /* complete type for func returning void */
void myfunc();
void myfunc(ifv *, ifv *); /* parameters incomplete */
void myfunc(cfv *, ifv *); /* complete only first parameter */
void myfunc(ifv *, cfv *); /* complete only first parameter */
/*
* All non-redundant so far. The type of myfunc is now complete in
* Standard C although not in GNC C, so any further declarations of
* all or parts of it are redundant.
*/
C also allows building up declarations by adding linkage info. This
is even more confusing.
GNUC also allows building up declarations by adding attribute info
one or several but not all attributes at a time. This is less confusing,
at least for the 1-at-a-time case. E.g.:
void panic(const char *, ...);
#ifdef __MUMBLE >= 99
void panic(const char * restrict, ...); /* add C99 feature */
#endif
void panic(const char *, ...) __dead2; /* add old GNU feature */
void panic(const char *, ...) __printflike(1, 2); /* newer GNU feature */
void panic(const char *, ...) __nonnull(1); /* even newer GNU feature */
Building up types is very confusing so you should rarely do it, but the
above is almost reasonable. Adding the restrict qualifier only for C99
and later is obfuscated in a different way using ifdefs for __restrict.
The bugs in "gcc -Wredundant-decls" accidentally detect the style bug
of using the building-up-types feature. This should be detected
under a different warning.
panic(9) is still missing both 'restrict' and __nonnull(1), though it
needs __nonull() even more than printf([39]) because a null panicstr
is magic (used for recursion detection).
Bruce
More information about the svn-src-head
mailing list