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:
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