diff --git a/parse.c b/parse.c index 4cda47d176e3ead2c25da8570fbb968a7c21784f..44f4b92504257c8d738743425bad70eec815e15f 100644 --- a/parse.c +++ b/parse.c @@ -1947,8 +1947,17 @@ static Node *unary(Token **rest, Token *tok) { if (equal(tok, "&")) return new_unary(ND_ADDR, cast(rest, tok->next), tok); - if (equal(tok, "*")) - return new_unary(ND_DEREF, cast(rest, tok->next), tok); + if (equal(tok, "*")) { + // [https://www.sigbus.info/n1570#6.5.3.2p4] This is an oddity + // in the C spec, but dereferencing a function shouldn't do + // anything. If foo is a function, `*foo`, `**foo` or `*****foo` + // are all equivalent to just `foo`. + Node *node = cast(rest, tok->next); + add_type(node); + if (node->ty->kind == TY_FUNC) + return node; + return new_unary(ND_DEREF, node, tok); + } if (equal(tok, "!")) return new_unary(ND_NOT, cast(rest, tok->next), tok); diff --git a/test/function.c b/test/function.c index 6160c3674a9cdac61776a926dbf5e309367319af..d4019524de2a853127a89e0ace8532651b0834dc 100644 --- a/test/function.c +++ b/test/function.c @@ -363,6 +363,8 @@ int main() { ASSERT(15, struct_test38().a[14]); ASSERT(20, struct_test38().a[19]); + ASSERT(5, (***add2)(2,3)); + printf("OK\n"); return 0; }