Hi Collin,

While testing a testdir for module 'endian' on gcc110.fsffrance.org
(in the GCC compilefarm), I get a compilation error. This machine has
a pretty old libc (glibc 2.17), but that ought to work anyway.

gcc -std=gnu11 -DHAVE_CONFIG_H -I. -I../../gltests -I..  
-DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. 
-I../../gltests/.. -I../gllib -I../../gltests/../gllib 
-I/home/haible/prefix64/include -Wall  -Wno-error -g -O2 -MT test-alignasof.o 
-MD -MP -MF .deps/test-alignasof.Tpo -c -o test-alignasof.o 
../../gltests/test-alignasof.c
In file included from /usr/include/stdlib.h:42:0,
                 from ./stdlib.h:36,
                 from ../../gltests/macros.h:22,
                 from ../../gltests/test-alignasof.c:24:
/usr/include/bits/waitstatus.h:79:15: error: duplicate member ‘__w_retcode’
  unsigned int __w_retcode:8;
               ^
/usr/include/bits/waitstatus.h:80:15: error: duplicate member ‘__w_coredump’
  unsigned int __w_coredump:1;
               ^
/usr/include/bits/waitstatus.h:81:15: error: duplicate member ‘__w_termsig’
  unsigned int __w_termsig:7;
               ^
/usr/include/bits/waitstatus.h:93:15: error: duplicate member ‘__w_stopsig’
  unsigned int __w_stopsig:8; /* Stopping signal.  */
               ^
/usr/include/bits/waitstatus.h:94:15: error: duplicate member ‘__w_stopval’
  unsigned int __w_stopval:8; /* W_STOPPED if stopped.  */
               ^
make[3]: *** [test-alignasof.o] Error 1

Preprocessing with "-E -dD" shows this snippet:

-----------------------------------------------------
# 65 "/usr/include/bits/waitstatus.h" 2 3 4

union wait
  {
    int w_status;
    struct
      {

 unsigned int __w_termsig:7;
 unsigned int __w_coredump:1;
 unsigned int __w_retcode:8;
 unsigned int:16;


 unsigned int:16;
 unsigned int __w_retcode:8;
 unsigned int __w_coredump:1;
 unsigned int __w_termsig:7;

      } __wait_terminated;
-----------------------------------------------------
This is obviously broken. It originated from this source code:

-----------------------------------------------------
union wait
  {
    int w_status;
    struct
      {
# if    __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned int __w_termsig:7; /* Terminating signal.  */
        unsigned int __w_coredump:1; /* Set if dumped core.  */
        unsigned int __w_retcode:8; /* Return code if exited normally.  */
        unsigned int:16;
# endif                         /* Little endian.  */
# if    __BYTE_ORDER == __BIG_ENDIAN
        unsigned int:16;
        unsigned int __w_retcode:8;
        unsigned int __w_coredump:1;
        unsigned int __w_termsig:7;
# endif                         /* Big endian.  */
      } __wait_terminated;
-----------------------------------------------------

which is correct.

The problem is that configure found:

  checking for endian.h... yes
  checking whether byte ordering is bigendian... yes
  checking if endian.h conforms to POSIX... no

and thus a replacement gllib/endian.h was generated. But it does not include
the original <endian.h>:

$ grep '# *include' gllib/endian.h
#include <stdint.h>
#include <byteswap.h>

and thus does not define the __BYTE_ORDER, __LITTLE_ENDIAN,
__BIG_ENDIAN macros that the other system header (<bits/waitstatus.h>)
expects.

In other words: When overriding a system header, you must conditionally
#include_next that system header. (There are exception to this rule,
such as <glob.h> or <obstack.h>. But in general this rule is valid.)
The system header can have made any number of additional definitions
or declarations, and other system headers (and user code) may rely on
these definitions or declarations.

Bruno




Reply via email to