scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 67cf8a126f8a96736a156e5edf2164a1669c9544
parent 22a9502ff7a3709825f324d1b717d8bc6d843d32
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date:   Fri, 27 Mar 2026 17:57:26 +0100

cc1: Promote char constants to int

The magnitude of a character constant should be the same
than the result of promoting a char to int, and it means
that in case of having a char with sign we have to convert
it to negative.

Diffstat:
Msrc/cmd/scc-cc/cc1/lex.c | 20++++++++++++++++----
Atests/cc/execute/0254-litchar.c | 12++++++++++++
Mtests/cc/execute/scc-tests.lst | 1+
3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/src/cmd/scc-cc/cc1/lex.c b/src/cmd/scc-cc/cc1/lex.c @@ -637,21 +637,26 @@ static int character(void) { int i, multi = 0; - Rune r, d; - Type *tp = inttype; + Rune r; + Type *tp; Symbol *sym; + long long d; + struct limits *lim; + tp = chartype; if (*input->p == 'L') { multi = 1; - tp = wchartype; input->p++; + tp = wchartype; } + lim = getlimits(tp); + d = 0; input->p++; for (i = 0; *input->p != '\''; i++) { r = decode(multi); - if (r > getlimits(tp)->max.i) + if (r > lim->max.i) warn("character too large for enclosing character literal type"); d |= r; input->p++; @@ -663,11 +668,18 @@ character(void) if (i > 1) warn("multi-character character constant"); + if (tp == chartype) { + if (tp->prop & TSIGNED && d > lim->max.i) + d -= getlimits(uchartype)->max.i + 1; + tp = inttype; + } + sym = newsym(NS_IDEN, NULL); sym->u.i = d; sym->type = tp; yylval.sym = sym; tok2str(); + return CONSTANT; } diff --git a/tests/cc/execute/0254-litchar.c b/tests/cc/execute/0254-litchar.c @@ -0,0 +1,12 @@ +int c = '\xff'; + +int +main(void) +{ + char c = -1; + + if ('\xff' > 0) + return !(c > 0); + else + return !(c < 0); +} diff --git a/tests/cc/execute/scc-tests.lst b/tests/cc/execute/scc-tests.lst @@ -244,3 +244,4 @@ 0251-mul.c 0252-literal.c 0253-maxconst.c +0254-litchar.c