pp-expression numbers always long long

Aka 'intmax_t', as recommended by newer standards.
For example
    if (-0x80000000 < 0) is false,
but
    #if (-0x80000000 < 0) is true
because in C, 0x80000000 is an unsigned int, Whereas in
a preprocessor expression, it is a signed long long, even
without LL suffix.
This commit is contained in:
grischka
2025-03-20 20:21:20 +01:00
parent f57cc34a0c
commit b3381269d7
3 changed files with 38 additions and 10 deletions

20
tccpp.c
View File

@@ -542,11 +542,7 @@ ST_FUNC const char *get_tok_str(int v, CValue *cv)
case TOK_CLLONG: case TOK_CLLONG:
case TOK_CULLONG: case TOK_CULLONG:
/* XXX: not quite exact, but only useful for testing */ /* XXX: not quite exact, but only useful for testing */
#ifdef _WIN32
sprintf(p, "%u", (unsigned)cv->i);
#else
sprintf(p, "%llu", (unsigned long long)cv->i); sprintf(p, "%llu", (unsigned long long)cv->i);
#endif
break; break;
case TOK_LCHAR: case TOK_LCHAR:
cstr_ccat(&cstr_buf, 'L'); cstr_ccat(&cstr_buf, 'L');
@@ -1493,8 +1489,7 @@ static int expr_preprocess(TCCState *s1)
if (tok != ')') if (tok != ')')
expect("')'"); expect("')'");
} }
tok = TOK_CINT; goto c_number;
tokc.i = c;
} else if (tok == TOK___HAS_INCLUDE || } else if (tok == TOK___HAS_INCLUDE ||
tok == TOK___HAS_INCLUDE_NEXT) { tok == TOK___HAS_INCLUDE_NEXT) {
t = tok; t = tok;
@@ -1504,12 +1499,13 @@ static int expr_preprocess(TCCState *s1)
c = parse_include(s1, t - TOK___HAS_INCLUDE, 1); c = parse_include(s1, t - TOK___HAS_INCLUDE, 1);
if (tok != ')') if (tok != ')')
expect("')'"); expect("')'");
tok = TOK_CINT; goto c_number;
tokc.i = c;
} else { } else {
/* if undefined macro, replace with zero */ /* if undefined macro, replace with zero */
tok = TOK_CINT; c = 0;
tokc.i = 0; c_number:
tok = TOK_CLLONG; /* type intmax_t */
tokc.i = c;
} }
tok_str_add_tok(str); tok_str_add_tok(str);
} }
@@ -2510,6 +2506,10 @@ static void parse_number(const char *p)
} }
} }
/* in #if/#elif expressions, all numbers have type (u)intmax_t anyway */
if (pp_expr)
lcount = 2;
/* Determine if it needs 64 bits and/or unsigned in order to fit */ /* Determine if it needs 64 bits and/or unsigned in order to fit */
if (ucount == 0 && b == 10) { if (ucount == 0 && b == 10) {
if (lcount <= (LONG_SIZE == 4)) { if (lcount <= (LONG_SIZE == 4)) {

View File

@@ -39,3 +39,24 @@ NOT OK
line __LINE__ line __LINE__
#define __LINE__ # ## # #define __LINE__ # ## #
line __LINE__ line __LINE__
----- 10 ------
/* preprocessor numbers are (u)intmax_t */
#if -2147483648 < 0
1 true
#endif
#if -0x80000000 < 0
2 true
#endif
#if -9223372036854775808U > 0
3 true
#endif
#if -0x8000000000000000 > 0 // unsigned by overflow
4 true
#endif
#if 1 << 31 > 2 && 1 << 32 > 2 && 1 << 63 < 2 && 1U << 63 > 2
5 true
#endif
#if (1<<29) * 11 >= 1<<32 && defined DDD << 63 < 0
6 true
#endif

View File

@@ -9,3 +9,10 @@ OK
----- 5 ------ ----- 5 ------
line 39 line 39
line ## line ##
----- 10 ------
1 true
2 true
3 true
4 true
5 true
6 true