(12-20-2024, 03:19 PM)Raion Wrote: In file included from /root/build-4.8/mips-sgi-irix6.5/libstdc++-v3/include/mips-sgi-irix6.5/bits/gthr-default.h:35:0, from /root/build-4.8/mips-sgi-irix6.5/libstdc++-v3/include/mips-sgi-irix6.5/bits/gthr.h:148
Read this file to see what the thread interface consists of. The header redirects to another header implementing the interface: the gthr-default.h is included when there is no threads API available, which is incorrect here. IRIX 6.5.20 and up conforms to Unix98 and so the correct implementation header is gthr-posix.h.
These programs should be compiled with a -D_PTHREADS parameter. The files gthr-posix.h and gthr-default.h have the same contents (they appear to be linked) so this doesn't change the following quoted lines.
Quote:error: array must be initialized with a brace-enclosed initializer
__gthread_mutex_t _M_mutex = __GTHREAD_MUTEX_INIT;
^ /root/build-4.8/mips-sgi-irix6.5/libstdc++-v3/include/ext/concurrence.h:255:32: error: array must be initialized with a brace-enclosed initializer
__gthread_cond_t _M_cond = __GTHREAD_COND_INIT;
Well, you can be sure that a mutex is definitely never an array. gthr-default.h defines the type __gthread_mutex_t as the same as pthread_mutex_t, which is defined in IRIX <sys/pthread.h> as being
Code:
typedef struct { long __D[8]; } pthread_mutex_t; /* mutex data */
so the type of _M_mutex is a struct containing an array of length 8. In a likewise manner __GTHREAD_MUTEX_INIT is defined in gthr-default.h to be the same as PTHREAD_MUTEX_INITIALIZER, which is defined n IRIX <pthread.h> as
Code:
#define PTHREAD_MUTEX_INITIALIZER { 0 }
Now you can see where the problem is. Initializing a struct containing an array of length 8 with { 0 } is eliding some of the braces: the outer braces are required to initialize the struct, and the embedded array initializer should normally have its own pair of braces. Whether such brace elision is allowed is a little unclear.
The C89
draft:
Quote:If the aggregate contains members that are aggregates or unions, or if the first member of a union is an aggregate or union, the rules apply recursively to the subaggregates or contained unions. If the initializer of a subaggregate or contained union begins with a left brace, the initializers enclosed by that brace and its matching right brace initialize the members of the subaggregate or the first member of the contained union. Otherwise, only enough initializers from the list are taken to account for the members of the first subaggregate or the first member of the contained union; any remaining initializers are left to initialize the next member of the aggregate of which the current subaggregate or contained union is a part.
(emphasis added)
implies that { 0 } is a valid initializer here, since the "list of initializers"—0—is used to "account for" the "members of the first subaggregate"—the long ints __D[0], __D[1], etc. The next paragraph of the draft:
Quote:If there are fewer initializers in a list than there are members of an aggregate, the remainder of the aggregate shall be initialized implicitly the same as objects that have static storage duration.
implies that after __D[0] is explicitly initialized to 0, the rest of the array—__D[1] to __D[7]—are implicitly initialized to 0. The examples support this interpretation:
Quote: struct { int a[3], b; } w[] = { { 1 }, 2 };
is a definition with an inconsistently bracketed initialization. It defines an array with two member structures: w[0].a[0] is 1 and w[1].a[0] is 2; all the other elements are zero.
However, the
same draft standard says:
Quote:A.6.2 Undefined behavior
The behavior in the following circumstances is undefined:
...
* An object with aggregate or union type with static storage duration has a non-brace-enclosed initializer, or an object with aggregate or union type with automatic storage duration has either a single expression initializer with a type other than that of the object or a non-brace-enclosed initializer (3.5.7).
The C99
Rationale says
Quote:Various implementations have parsed aggregate initializers with partially elided braces differently.
The Standard has reaffirmed the top-down parse described in K&R. Although the construct is allowed, and its parse well defined, the C89 Committee urges programmers to avoid partially elided initializers because such initializations can be quite confusing to read.
QUIET CHANGE IN C89
Code which relies on a bottom-up parse of aggregate initializers with partially elided braces will not yield the expected initialized object.
C++
apparently supports this same syntax.
The situation of the following error message is the same, with the corresponding definitions of __gthread_cond_t, pthread_cond_t, and PTHREAD_COND_INITIALIZER, which are defined the same way in the same files. In the end I'm not sure why GCC doesn't accept the code since it looks OK according to the standards. Is this using -Werror?