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