diff options
| author | Michael Matz <matz@suse.de> | 2016-07-14 04:09:49 +0200 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-15 17:47:08 +0100 |
| commit | 662338f116c3b87c78ddb113e8e63f6329fe307f (patch) | |
| tree | bdf415f6a66394a6ffc7bcf252b44edb04a491f9 | |
| parent | e034853b38907440142107eb689c5dd6c6621fca (diff) | |
| download | tinycc-662338f116c3b87c78ddb113e8e63f6329fe307f.tar.gz tinycc-662338f116c3b87c78ddb113e8e63f6329fe307f.tar.bz2 | |
Fix function to pointer conversion
This snippet is valid:
void foo(void);
... foo + 42 ...
the function designator is converted to pointer to function
implicitely. gen_op didn't do that and bailed out.
| -rw-r--r-- | tccgen.c | 13 | ||||
| -rw-r--r-- | tests/tcctest.c | 7 |
2 files changed, 20 insertions, 0 deletions
@@ -1926,6 +1926,7 @@ ST_FUNC void gen_op(int op) int u, t1, t2, bt1, bt2, t; CType type1; +redo: t1 = vtop[-1].type.t; t2 = vtop[0].type.t; bt1 = t1 & VT_BTYPE; @@ -1933,6 +1934,18 @@ ST_FUNC void gen_op(int op) if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) { tcc_error("operation on a struct"); + } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) { + if (bt2 == VT_FUNC) { + mk_pointer(&vtop->type); + gaddrof(); + } + if (bt1 == VT_FUNC) { + vswap(); + mk_pointer(&vtop->type); + gaddrof(); + vswap(); + } + goto redo; } else if (bt1 == VT_PTR || bt2 == VT_PTR) { /* at least one operand is a pointer */ /* relationnal op: must be both pointers */ diff --git a/tests/tcctest.c b/tests/tcctest.c index 0b894aa..8aa50ab 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1847,6 +1847,7 @@ void funcptr_test() int dummy; void (*func)(int); } st1; + long diff; printf("funcptr:\n"); func = # @@ -1862,6 +1863,12 @@ void funcptr_test() printf("sizeof2 = %d\n", sizeof funcptr_test); printf("sizeof3 = %d\n", sizeof(&funcptr_test)); printf("sizeof4 = %d\n", sizeof &funcptr_test); + a = 0; + func = num + a; + diff = func - num; + func(42); + (func + diff)(42); + (num + a)(43); } void lloptest(long long a, long long b) |
