The avr-rtems port will not build using a trunk compiler on a system
with a reasonably modern glibc.
If we look at newlib-stdint.h, we have these wonderfully convoluted
conditionals like:
#define INT8_TYPE (CHAR_TYPE_SIZE == 8 ? "signed char" : 0)
They get more complex, but essentially they have the property that if
none of the tests hold true, the default value is "0", ie, NULL.
In the case of avr-rtems the problematic code is for the char16_t type
initialized by c-common.c:
char16_type_node = get_identifier (CHAR16_TYPE);
CHAR16_TYPE is defined as:
#ifdef UINT_LEAST16_TYPE
#define CHAR16_TYPE UINT_LEAST16_TYPE
#else
#define CHAR16_TYPE "short unsigned int"
#endif
So if we go to newlib-stdint.h we have:
#define UINT_LEAST16_TYPE (UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ?
UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
Where under the hood a short's size varies on the avr port based on
target flags.
Soooo, to see how this causes problems it's best to show you the cpp
expanded code. If you have a weak stomach, stop reading immediately.
Here's the problematic line in source form:
char16_type_node = get_identifier (CHAR16_TYPE);
And cpp expanded for avr-rtems:
c_global_trees[CTI_CHAR16_TYPE] = (__builtin_constant_p
(((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16
? "shor
t unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8
: 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char" : 0) ?
(((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? (
((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16
? "short unsigned int" : (((global_options.x_target_flags & (1 << 4)) !=
0) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char"
: 0) : ((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16)
== 8 ? 16 : 32) == 32) ? "long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 32 ?
"unsigned int" : ((((g
lobal_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 32
? "short unsigned int" : (8) == 32 ? "unsigned char" : 0) ? ((((((global_
options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16 : 32) ==
32) ? "long unsigned int" : (((global_options.x_target_flags & (1 << 4))
!= 0) ? 8 : 16) == 32 ? "unsigned int" : ((((global_options.x_targe
t_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 32
? "short unsigned int" : (8) == 32 ? "unsigned char" : 0) :
(((((global_options.x_target_flags
& (1 << 4)) != 0) ? 8 : 16) == 8 ? 16 : 32) == 64 ? "long unsigned
int" : ((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) ==
8 ? 32 : 64) == 64 ? "long long unsigned int" : (((global_options.x_ta
rget_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ? "unsigned int" : 0) ?
(((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16
: 32) == 64 ? "long unsigned int" : ((((global_options.x_target_flag
s & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32 : 64) == 64 ? "long long
unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 64 ? "unsigned int" : 0) : 0)) ? get_identifier_with_length (((((
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16
? "short unsigned int" : (((global_options.x_target_flags & (1 << 4))
!= 0) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char" :
0) ? (((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8
? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) :
16) == 16 ? "short unsigned int" : (((global_options.x_target_flags & (1
<< 4)) != 0) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned
char" : 0) : ((((((global_options.x_target_flags & (1 << 4)) != 0)
? 8 : 16) == 8 ? 16 : 32) == 32) ? "long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 32 ?
"unsigned int" : ((((global_options.x_target_flags & (1 << 4)) != 0) ? 8
: 16) == 8
? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) ==
32 ? "short unsigned int" : (8) == 32 ? "unsigned char" : 0) ?
((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16 :
32) == 32) ? "long unsigned int" : (((global_options.x_target_flags &
(1 << 4)) != 0) ? 8 : 16) == 32 ? "unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x
_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 32 ? "short unsigned
int" : (8) == 32 ? "unsigned char" : 0) :
(((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16
: 32) == 64 ? "long uns
igned int" : ((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 8 ? 32 : 64) == 64 ? "long long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ?
"unsigned int"
: 0) ? (((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) ==
8 ? 16 : 32) == 64 ? "long unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32
: 64) == 64 ? "long lo
ng unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ?
8 : 16) == 64 ? "unsigned int" : 0) : 0)), strlen
(((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_option
s.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16 ? "short
unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char" : 0) ? (((((gl
obal_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16
? "short unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0
) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char" : 0) :
((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
16 : 32) == 32) ? "long unsigned int" : (((global_options.x_target_
flags & (1 << 4)) != 0) ? 8 : 16) == 32 ? "unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 32
? "short
unsigned int" : (8) == 32 ? "unsigned char" : 0) ?
((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
16 : 32) == 32) ? "long unsigned int" : (((global_options.x_target_flags
& (1 << 4)) !=
0) ? 8 : 16) == 32 ? "unsigned int" : ((((global_options.x_target_flags
& (1 << 4)) != 0) ? 8 : 16) == 8 ? (((global_options.x_target_flags & (1
<< 4)) != 0) ? 8 : 16) : 16) == 32 ? "short unsigned int" : (8) =
= 32 ? "unsigned char" : 0) : (((((global_options.x_target_flags & (1 <<
4)) != 0) ? 8 : 16) == 8 ? 16 : 32) == 64 ? "long unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32
: 64) == 64 ? "long long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ?
"unsigned int" : 0) ? (((((global_options.x_target_flags & (1 << 4)) !=
0) ? 8 : 16) == 8 ? 16 : 32
) == 64 ? "long unsigned int" : ((((global_options.x_target_flags & (1
<< 4)) != 0) ? 8 : 16) == 8 ? 32 : 64) == 64 ? "long long unsigned int"
: (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 6
4 ? "unsigned int" : 0) : 0))) : get_identifier
(((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16
? "short unsigned
int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) ==
16 ? "unsigned int" : (8) == 16 ? "unsigned char" : 0) ?
(((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_o
ptions.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 16 ? "short
unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned char" : 0) : ((
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16
: 32) == 32) ? "long unsigned int" : (((global_options.x_target_flags &
(1 << 4)) != 0) ? 8 : 16) == 32 ? "unsigned int" : ((((global_opti
ons.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ?
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) : 16) == 32
? "short unsigned int" : (8) == 32 ? "unsigned char" : 0) ?
((((((global_options.x_
target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16 : 32) == 32) ? "long
unsigned int" : (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 32 ? "unsigned int" : ((((global_options.x_target_flags &
(1 << 4)) != 0) ? 8 : 16) == 8 ? (((global_options.x_target_flags & (1
<< 4)) != 0) ? 8 : 16) : 16) == 32 ? "short unsigned int" : (8) == 32 ?
"unsigned char" : 0) : (((((global_options.x_target_flags & (1 << 4
)) != 0) ? 8 : 16) == 8 ? 16 : 32) == 64 ? "long unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32
: 64) == 64 ? "long long unsigned int" : (((global_options.x_target_flags
& (1 << 4)) != 0) ? 8 : 16) == 64 ? "unsigned int" : 0) ?
(((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 16
: 32) == 64 ? "long unsigned int" : ((((global_options.x_target_flags &
(1 <<
4)) != 0) ? 8 : 16) == 8 ? 32 : 64) == 64 ? "long long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ?
"unsigned int" : 0) : 0)));
OK, so clean up after you just lost your lunch...
If you look closely, you'll see a calls to strlen in there. I'll
highlight one:
strlen (((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16)
== 8 ? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) :
16) == 16 ? "short unsigned int" : (((global_options.x_target_flags & (1
<< 4)) != 0) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned
char" : 0) ? (((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 8 ? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16)
: 16) == 16 ? "short unsigned int" : (((global_options.x_target_flags &
(1 << 4)) != 0) ? 8 : 16) == 16 ? "unsigned int" : (8) == 16 ? "unsigned
char" : 0) : ((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) == 8 ? 16 : 32) == 32) ? "long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 32 ?
"unsigned int" : ((((global_options.x_target_flags & (1 << 4)) != 0) ? 8
: 16) == 8 ? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) : 16) == 32 ? "short unsigned int" : (8) == 32 ? "unsigned char" :
0) ? ((((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) ==
8 ? 16 : 32) == 32) ? "long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 32 ?
"unsigned int" : ((((global_options.x_target_flags & (1 << 4)) != 0) ? 8
: 16) == 8 ? (((global_options.x_target_flags & (1 << 4)) != 0) ? 8 :
16) : 16) == 32 ? "short unsigned int" : (8) == 32 ? "unsigned char" :
0) : (((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8
? 16 : 32) == 64 ? "long unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32
: 64) == 64 ? "long long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ?
"unsigned int" : 0) ? (((((global_options.x_target_flags & (1 << 4)) !=
0) ? 8 : 16) == 8 ? 16 : 32) == 64 ? "long unsigned int" :
((((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 8 ? 32
: 64) == 64 ? "long long unsigned int" :
(((global_options.x_target_flags & (1 << 4)) != 0) ? 8 : 16) == 64 ?
"unsigned int" : 0) : 0))
Note how "0" might get passed to strlen. That's verboten and GCC
naturally complains:
In file included from ../../../gcc/gcc/c-family/c-common.c:32:0:
../../../gcc/gcc/c-family/c-common.c: In function ‘void
c_common_nodes_and_builtins()’:
../../../gcc/gcc/stringpool.h:39:53: error: null argument where non-null
required (argument 1) [-Werror=nonnull]
? get_identifier_with_length ((str), strlen (str)) \
^
../../../gcc/gcc/c-family/c-common.c:6008:22: note: in expansion of
macro ‘get_identifier’
char16_type_node = get_identifier (CHAR16_TYPE);
^
../../../gcc/gcc/stringpool.h:39:53: error: null argument where non-null
required (argument 1) [-Werror=nonnull]
? get_identifier_with_length ((str), strlen (str)) \
^
../../../gcc/gcc/c-family/c-common.c:6024:22: note: in expansion of
macro ‘get_identifier’
char32_type_node = get_identifier (CHAR32_TYPE);
^
cc1plus: all warnings being treated as errors
In the interest of keeping my sanity, I'd just change that last default
value to something like "unknown type error" or somesuch. But I'm sure
there's a better way. Suggestions?
FWIW, where's the set of broken type definition macros I could find easily:
./config/newlib-stdint.h:#define INT8_TYPE (CHAR_TYPE_SIZE == 8 ?
"signed char" : 0)
./config/newlib-stdint.h:#define INT16_TYPE (SHORT_TYPE_SIZE == 16 ?
"short int" : INT_TYPE_SIZE == 16 ? "int" : CHAR_TYPE_SIZE == 16 ?
"signed char" : 0)
./config/newlib-stdint.h:#define INT32_TYPE (STDINT_LONG32 ? "long int"
: INT_TYPE_SIZE == 32 ? "int" : SHORT_TYPE_SIZE == 32 ? "short int" :
CHAR_TYPE_SIZE == 32 ? "signed char" : 0)
./config/newlib-stdint.h:#define INT64_TYPE (LONG_TYPE_SIZE == 64 ?
"long int" : LONG_LONG_TYPE_SIZE == 64 ? "long long int" : INT_TYPE_SIZE
== 64 ? "int" : 0)
./config/newlib-stdint.h:#define UINT8_TYPE (CHAR_TYPE_SIZE == 8 ?
"unsigned char" : 0)
./config/newlib-stdint.h:#define UINT16_TYPE (SHORT_TYPE_SIZE == 16 ?
"short unsigned int" : INT_TYPE_SIZE == 16 ? "unsigned int" :
CHAR_TYPE_SIZE == 16 ? "unsigned char" : 0)
./config/newlib-stdint.h:#define UINT32_TYPE (STDINT_LONG32 ? "long
unsigned int" : INT_TYPE_SIZE == 32 ? "unsigned int" : SHORT_TYPE_SIZE
== 32 ? "short unsigned int" : CHAR_TYPE_SIZE == 32 ? "unsigned char" : 0)
./config/newlib-stdint.h:#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ?
"long unsigned int" : LONG_LONG_TYPE_SIZE == 64 ? "long long unsigned
int" : INT_TYPE_SIZE == 64 ? "unsigned int" : 0)
./config/newlib-stdint.h:#define INT_LEAST8_TYPE (INT8_TYPE ? INT8_TYPE
: INT16_TYPE ? INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ?
INT64_TYPE : 0)
./config/newlib-stdint.h:#define INT_LEAST16_TYPE (INT16_TYPE ?
INT16_TYPE : INT32_TYPE ? INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
./config/newlib-stdint.h:#define INT_LEAST32_TYPE (INT32_TYPE ?
INT32_TYPE : INT64_TYPE ? INT64_TYPE : 0)
./config/newlib-stdint.h:#define UINT_LEAST8_TYPE (UINT8_TYPE ?
UINT8_TYPE : UINT16_TYPE ? UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE :
UINT64_TYPE ? UINT64_TYPE : 0)
./config/newlib-stdint.h:#define UINT_LEAST16_TYPE (UINT16_TYPE ?
UINT16_TYPE : UINT32_TYPE ? UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
./config/newlib-stdint.h:#define UINT_LEAST32_TYPE (UINT32_TYPE ?
UINT32_TYPE : UINT64_TYPE ? UINT64_TYPE : 0)
./config/avr/avr-stdint.h:#define INT64_TYPE (INT_TYPE_SIZE == 16 ?
"long long int" : 0)
./config/avr/avr-stdint.h:#define UINT64_TYPE (INT_TYPE_SIZE == 16 ?
"long long unsigned int" : 0)
You might legitimately ask why something like h8300-rtems doesn't hit
this. I believe it's because the h8300 has a constant SHORT_TYPE_SIZE,
which is enough to simplify things to the point where GCC knows NULL
isn't going to get passed to strlen. Contrast to the avr where
SHORT_TYPE_SIZE varies.
Thoughts or suggestions?
jeff