aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Chambers <andrewchambers@fastmail.com>2019-02-27 20:42:23 +1300
committerMichael Forney <mforney@mforney.org>2019-02-27 21:59:11 -0800
commit7c2089414f2d6476c093a08bb7305e72a89b552c (patch)
tree3a1100422deb37769368df99ecb78800a2fa5b62
parentde85378a20b2a190d4e8a5ce3156a8bdbc682bcc (diff)
downloadcproc-7c2089414f2d6476c093a08bb7305e72a89b552c.tar.xz
Implement __typeof__.
-rw-r--r--decl.c9
-rw-r--r--pp.c1
-rw-r--r--tests/typeof.c20
-rw-r--r--tests/typeof.qbe54
-rw-r--r--token.h1
5 files changed, 85 insertions, 0 deletions
diff --git a/decl.c b/decl.c
index 870d72a..7bd2cbb 100644
--- a/decl.c
+++ b/decl.c
@@ -325,6 +325,15 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspecifier *fs, int *a
++ntypes;
next();
break;
+ case T__TYPEOF__:
+ next();
+ expect(TLPAREN, "after '__typeof__'");
+ t = typename(s);
+ if (!t)
+ t = expr(s)->type;
+ ++ntypes;
+ expect(TRPAREN, "to close '__typeof__'");
+ break;
/* 6.7.5 Alignment specifier */
case T_ALIGNAS:
diff --git a/pp.c b/pp.c
index 3cb4244..2c47d59 100644
--- a/pp.c
+++ b/pp.c
@@ -27,6 +27,7 @@ keyword(struct token *tok)
{"_Noreturn", T_NORETURN},
{"_Static_assert", T_STATIC_ASSERT},
{"_Thread_local", T_THREAD_LOCAL},
+ {"__typeof__", T__TYPEOF__},
{"auto", TAUTO},
{"break", TBREAK},
{"case", TCASE},
diff --git a/tests/typeof.c b/tests/typeof.c
new file mode 100644
index 0000000..d6a218f
--- /dev/null
+++ b/tests/typeof.c
@@ -0,0 +1,20 @@
+int v;
+typedef int* t;
+int f() {v = 1; return 0;}
+int main() {
+ __typeof__(f()) x = 123;
+ __typeof__(t) y = &x;
+
+ if (x != 123)
+ return 1;
+ if (*y != 123)
+ return 2;
+ if (sizeof(y) != sizeof(int*))
+ return 3;
+ if (sizeof(x) != sizeof(int))
+ return 4;
+ if (v != 0)
+ return 5;
+
+ return 0;
+}
diff --git a/tests/typeof.qbe b/tests/typeof.qbe
new file mode 100644
index 0000000..5cd138f
--- /dev/null
+++ b/tests/typeof.qbe
@@ -0,0 +1,54 @@
+export
+function w $f() {
+@start.1
+@body.2
+ storew 1, $v
+ ret 0
+}
+export
+function w $main() {
+@start.3
+ %.1 =l alloc4 4
+ %.3 =l alloc8 8
+@body.4
+ %.2 =l add %.1, 0
+ storew 123, %.2
+ %.4 =l add %.3, 0
+ storel %.1, %.4
+ %.5 =w loadsw %.1
+ %.6 =w cnew %.5, 123
+ %.7 =w cnew %.6, 0
+ jnz %.7, @if_true.5, @if_false.6
+@if_true.5
+ ret 1
+@if_false.6
+ %.8 =l loadl %.3
+ %.9 =w loadsw %.8
+ %.10 =w cnew %.9, 123
+ %.11 =w cnew %.10, 0
+ jnz %.11, @if_true.7, @if_false.8
+@if_true.7
+ ret 2
+@if_false.8
+ %.12 =w cnel 8, 8
+ %.13 =w cnew %.12, 0
+ jnz %.13, @if_true.9, @if_false.10
+@if_true.9
+ ret 3
+@if_false.10
+ %.14 =w cnel 4, 4
+ %.15 =w cnew %.14, 0
+ jnz %.15, @if_true.11, @if_false.12
+@if_true.11
+ ret 4
+@if_false.12
+ %.16 =w loadsw $v
+ %.17 =w cnew %.16, 0
+ %.18 =w cnew %.17, 0
+ jnz %.18, @if_true.13, @if_false.14
+@if_true.13
+ ret 5
+@if_false.14
+ ret 0
+}
+export data $v = align 4 { z 4 }
diff --git a/token.h b/token.h
index ed4483c..ad19311 100644
--- a/token.h
+++ b/token.h
@@ -54,6 +54,7 @@ enum tokenkind {
T_NORETURN,
T_STATIC_ASSERT,
T_THREAD_LOCAL,
+ T__TYPEOF__,
/* punctuator */
TLBRACK,