commit 36ddcbc0a20ca1364fcc516dfef3a9d0b79871f7
parent 84ebbc029a7f0918783284562c38a0b8fa276f1a
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Fri, 1 May 2026 15:19:17 -0700
merge: lexer char-literal type fix
Diffstat:
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/cc/cc.scm b/cc/cc.scm
@@ -6497,7 +6497,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