diff --git a/NEWS b/NEWS index fbf9f4cc..35a561d9 100644 --- a/NEWS +++ b/NEWS @@ -69,7 +69,11 @@ GNU Bison NEWS Bison templates now prefer signed to unsigned integer types when either will do, as the signed types are less error-prone and allow - for better checking with 'gcc -fsanitize=undefined'. + for better checking with 'gcc -fsanitize=undefined'. Also, the + types chosen are now portable to unusual machines where char, short and + int are all the same width. On non-GNU platforms this may entail + including and (if available) to define integer types + and constants. * Noteworthy changes in release 3.4.2 (2019-09-12) [stable] diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c index 10708627..8d32af56 100644 --- a/data/skeletons/yacc.c +++ b/data/skeletons/yacc.c @@ -114,7 +114,7 @@ m4_ifset([b4_parse_param], [b4_args(b4_parse_param), ])]) # --------------------- # Return a narrow int type able to handle numbers ranging from # MIN to MAX (included). Overwrite the version from c.m4, -# so that the user can override the shorter types. +# so that the code can use C99 types if available. m4_define([b4_int_type], [m4_if(b4_ints_in($@, [-127], [127]), [1], [yytype_int8], b4_ints_in($@, [0], [255]), [1], [yytype_uint8], @@ -388,26 +388,54 @@ m4_if(b4_api_prefix, [yy], [], # undef short #endif -#ifdef YYTYPE_UINT8 -typedef YYTYPE_UINT8 yytype_uint8; -#else -typedef unsigned char yytype_uint8; +/* On compilers that do not define __PTRDIFF_MAX__ etc., include + and (if available) so that the code can + choose integer types of a good width. */ + +#ifndef __PTRDIFF_MAX__ +# include /* INFRINGES ON USER NAME SPACE */ +# if defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ +# include /* INFRINGES ON USER NAME SPACE */ +# endif #endif -#ifdef YYTYPE_INT8 -typedef YYTYPE_INT8 yytype_int8; +/* Narrow types that promote to a signed type and that can represent a + signed or unsigned integer of at least N bits. In tables they can + save space and decrease cache pressure. Promoting to a signed type + helps avoid bugs in integer arithmetic. */ + +#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST8_TYPE__ yytype_uint8; +#elif defined UINT_LEAST8_MAX && UINT_LEAST8_MAX <= INT_MAX +typedef uint_least8_t yytype_uint8; +#elif UCHAR_MAX <= INT_MAX +typedef unsigned char yytype_uint8; +#else +typedef short yytype_uint8; +#endif + +#if defined __INT_LEAST8_MAX__ && __INT_LEAST8_MAX__ <= __INT_MAX__ +typedef __INT_LEAST8_TYPE__ yytype_int8; +#elif defined INT_LEAST8_MAX && INT_LEAST8_MAX <= INT_MAX +typedef int_least8_t yytype_int8; #else typedef signed char yytype_int8; #endif -#ifdef YYTYPE_UINT16 -typedef YYTYPE_UINT16 yytype_uint16; -#else +#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__ +typedef __UINT_LEAST16_TYPE__ yytype_uint16; +#elif defined UINT_LEAST16_MAX && UINT_LEAST16_MAX <= INT_MAX +typedef uint_least16_t yytype_uint16; +#elif USHRT_MAX <= INT_MAX typedef unsigned short yytype_uint16; +#else +typedef int yytype_uint16; #endif -#ifdef YYTYPE_INT16 -typedef YYTYPE_INT16 yytype_int16; +#if defined __INT_LEAST16_MAX__ && __INT_LEAST16_MAX__ <= __INT_MAX__ +typedef __INT_LEAST16_TYPE__ yytype_int16; +#elif defined INT_LEAST16_MAX && INT_LEAST16_MAX <= INT_MAX +typedef int_least16_t yytype_int16; #else typedef short yytype_int16; #endif @@ -416,17 +444,14 @@ typedef short yytype_int16; # if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__ # define YYPTRDIFF_T __PTRDIFF_TYPE__ # define YYPTRDIFF_MAXIMUM __PTRDIFF_MAX__ -# elif defined ptrdiff_t && defined PTRDIFF_MAX +# elif defined PTRDIFF_MAX +# ifndef ptrdiff_t +# include /* INFRINGES ON USER NAME SPACE */ +# endif # define YYPTRDIFF_T ptrdiff_t # define YYPTRDIFF_MAXIMUM PTRDIFF_MAX -# elif defined __STDC_VERSION__ && 199901 <= __STDC_VERSION__ -# include /* INFRINGES ON USER NAME SPACE */ -# define YYPTRDIFF_T ptrdiff_t -# include /* INFRINGES ON USER NAME SPACE */ -# define YYPTRDIFF_MAXIMUM PTRDIFF_MAX # else # define YYPTRDIFF_T long -# include /* INFRINGES ON USER NAME SPACE */ # define YYPTRDIFF_MAXIMUM LONG_MAX # endif #endif diff --git a/doc/bison.texi b/doc/bison.texi index 6f4ca9e2..c78bd31e 100644 --- a/doc/bison.texi +++ b/doc/bison.texi @@ -1447,13 +1447,13 @@ anything other than their usual meanings. In some cases the Bison parser implementation file includes system headers, and in those cases your code should respect the identifiers -reserved by those headers. On some non-GNU hosts, @code{}, -@code{}, @code{}, and @code{} are -included as needed to declare memory allocators and related types. +reserved by those headers. On some non-GNU hosts, @code{}, +@code{}, @code{} (if available), and @code{} +are included to declare memory allocators and integer types and constants. @code{} is included if message translation is in use (@pxref{Internationalization}). Other system headers may be included -if you define @code{YYDEBUG} to a nonzero value (@pxref{Tracing, -,Tracing Your Parser}). +if you define @code{YYDEBUG} (@pxref{Tracing, ,Tracing Your Parser}) or +@code{YYSTACK_USE_ALLOCA} (@pxref{Table of Symbols}) to a nonzero value. @node Stages @section Stages in Using Bison diff --git a/src/parse-gram.y b/src/parse-gram.y index b4132841..043fa581 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -112,11 +112,6 @@ /* A string that describes a char (e.g., 'a' -> "'a'"). */ static char const *char_name (char); - #define YYTYPE_INT16 int_fast16_t - #define YYTYPE_INT8 int_fast8_t - #define YYTYPE_UINT16 uint_fast16_t - #define YYTYPE_UINT8 uint_fast8_t - /* Add style to semantic values in traces. */ static void tron (FILE *yyo); static void troff (FILE *yyo);