commit 578b721938477b60df9847585fb1bd4dec693841
parent 5dbea4132c4faacb1c5a1056b67a75ce698c36bf
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 1 May 2026 15:07:49 -0700
cc: type integer character constants as int (§6.4.4.4)
parse-primary was pushing CHAR tokens with type %t-i8, which made
sizeof('A') == 1 and caused '\xFF' to sign-extend to -1 instead of
having int value 255. Per C99 §6.4.4.4, an integer character constant
has type int. The const-expression path already used %t-i32; align
the runtime path with it.
New test 200-lex-char-type.c covers both the sizeof and the value
paths.
Diffstat:
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/cc/cc.scm b/cc/cc.scm
@@ -6637,7 +6637,8 @@
(cg-push-imm (ps-cg ps) %t-i32 n))
(($ tok? (kind CHAR) (value ,c))
(advance ps)
- (cg-push-imm (ps-cg ps) %t-i8 c))
+ ;; C99 §6.4.4.4: an integer character constant has type int.
+ (cg-push-imm (ps-cg ps) %t-i32 c))
(($ tok? (kind STR) (value ,s))
(advance ps)
(cg-push-string (ps-cg ps) s))
diff --git a/tests/cc/200-lex-char-type.c b/tests/cc/200-lex-char-type.c
@@ -0,0 +1,29 @@
+/* C99 §6.4.4.4: "An integer character constant has type int."
+ *
+ * Therefore sizeof('A') must equal sizeof(int), not sizeof(char).
+ * Also the value of '\xFF' as a character constant has type int and,
+ * when its impl-defined value is non-negative (here 255), should
+ * compare equal to the int 255 — a char-typed constant would
+ * sign-extend to -1 instead.
+ */
+
+int test_sizeof(void) {
+ if (sizeof('A') != sizeof(int)) return 1;
+ if (sizeof('A') == sizeof(char)) return 2;
+ return 0;
+}
+
+int test_value(void) {
+ /* '\xFF' must have int rank; promotion of an int 255 keeps 255. */
+ int x = '\xFF';
+ if (x == -1) return 1; /* would happen if typed as signed i8 */
+ if (x != 255) return 2;
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ int r;
+ if ((r = test_sizeof())) return 10 + r;
+ if ((r = test_value())) return 20 + r;
+ return 0;
+}
diff --git a/tests/cc/200-lex-char-type.expected-exit b/tests/cc/200-lex-char-type.expected-exit
@@ -0,0 +1 @@
+0