avr-rtems broken on trunk -- need advice

Jeff Law law@redhat.com
Mon Oct 12 20:02:00 GMT 2015


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



More information about the Gcc mailing list