Numerical constant scanner requires explicitly 32-bit sized type for cross-platform consistency

This commit is contained in:
bbbradsmith 2023-05-03 19:27:37 -04:00
parent 49bd568113
commit e3cb8dfb9b
3 changed files with 29 additions and 7 deletions

View File

@ -39,6 +39,7 @@
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <inttypes.h>
/* common */
#include "chartype.h"
@ -151,6 +152,11 @@ static const struct Keyword {
#define IT_ULONG 0x08
/* Internal type for numeric constant scanning.
** Size must be explicit for cross-platform uniformity.
*/
typedef uint32_t scan_t;
/*****************************************************************************/
/* code */
@ -521,7 +527,7 @@ static void NumericConst (void)
int IsFloat;
char C;
unsigned DigitVal;
unsigned long IVal; /* Value */
scan_t IVal; /* Scanned value. */
int Overflow;
/* Get the pp-number first, then parse on it */
@ -584,19 +590,19 @@ static void NumericConst (void)
SB_Clear (&Src);
break;
}
if ((((unsigned long)(IVal * Base)) / Base) != IVal) {
if (((scan_t)(IVal * Base) / Base) != IVal) {
Overflow = 1;
}
IVal = IVal * Base;
if (((unsigned long)(IVal + DigitVal)) < IVal) {
if (((scan_t)(IVal + DigitVal)) < IVal) {
Overflow = 1;
}
IVal += DigitVal;
SB_Skip (&Src);
}
if (Overflow) {
Error ("Numerical constant \"%s\" too large for internal 32-bit representation",
SB_GetConstBuf (&Src));
Error ("Numerical constant \"%s\" too large for internal %d-bit representation",
SB_GetConstBuf (&Src), (int)(sizeof(IVal)*8));
}
/* Distinguish between integer and floating point constants */

View File

@ -20,3 +20,4 @@
#define SIZEOF_LONG_32BIT
#define UNSIGNED_CHARS
#define UNSIGNED_BITFIELDS
#define INTEGER_CONSTANT_MAX_32BIT

View File

@ -4,6 +4,14 @@
!!LICENCE!! own, freely distributeable for non-profit. read CPYRIGHT.LCC
*/
/* INTEGER_CONSTANT_MAX_32BIT
** This suppresses constants longer than 32-bit, which are now an error:
** https://github.com/cc65/cc65/pull/2084
** Because cc65's internal representation is implicitly/explicitly
** 32-bit in many places, values larger than this aren't representable,
** but also can't be checked for overflow once accepted.
*/
#include "common.h"
struct defs {
@ -62,7 +70,12 @@ long pow2(long n) {
return s;
}
long d[39], o[39], x[39];
#ifndef INTEGER_CONSTANT_MAX_32BIT
#define CTCOUNT 39
#else
#define CTCOUNT 36
#endif
long d[CTCOUNT], o[CTCOUNT], x[CTCOUNT];
#ifndef NO_OLD_FUNC_DECL
s241(pd0)
@ -212,13 +225,15 @@ int s241(struct defs *pd0) {
d[33] = 1073741823; o[33] = 07777777777; x[33] = 0x3fffffff;
d[34] = 1073741824; o[34] = 010000000000; x[34] = 0x40000000;
d[35] = 4294967295; o[35] = 037777777777; x[35] = 0xffffffff;
#if CTCOUNT > 36
d[36] = 4294967296; o[36] = 040000000000; x[36] = 0x100000000;
d[37] = 68719476735; o[37] = 0777777777777; x[37] = 0xfffffffff;
d[38] = 68719476736; o[38] = 01000000000000; x[38] = 0x1000000000;
#endif
/* WHEW! */
for (j=0; j<39; j++){
for (j=0; j<CTCOUNT; j++){
if ( g[j] != d[j]
|| d[j] != o[j]
|| o[j] != x[j]) {