aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tccgen.c13
-rw-r--r--tests/tcctest.c7
2 files changed, 20 insertions, 0 deletions
diff --git a/tccgen.c b/tccgen.c
index 6d72ab9..f49caa6 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -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)