From 0028b14071bd102e79be22abcbe1f555e9ffa3e2 Mon Sep 17 00:00:00 2001 From: acqn Date: Thu, 5 Oct 2023 17:48:16 +0800 Subject: [PATCH] The type category in a function definition cannot be inherited from a typedef. --- src/cc65/compile.c | 28 ++++++++++++++++++---------- test/err/bug2020-definition.c | 6 ++++++ test/val/bug2020-ok.c | 16 ++++++++++++++++ 3 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 test/err/bug2020-definition.c create mode 100644 test/val/bug2020-ok.c diff --git a/src/cc65/compile.c b/src/cc65/compile.c index 1cb109bbe..7bf3cd8ab 100644 --- a/src/cc65/compile.c +++ b/src/cc65/compile.c @@ -65,6 +65,7 @@ #include "preproc.h" #include "standard.h" #include "staticassert.h" +#include "typecmp.h" #include "symtab.h" @@ -325,17 +326,24 @@ static void Parse (void) if (Sym && IsTypeFunc (Sym->Type)) { /* Function */ - if (!comma) { - if (CurTok.Tok == TOK_SEMI) { - /* Prototype only */ - NextToken (); - } else if (CurTok.Tok == TOK_LCURLY) { - /* Parse the function body */ - NewFunc (Sym, FuncDef); - - /* Make sure we aren't omitting any work */ - CheckDeferredOpAllDone (); + if (CurTok.Tok == TOK_SEMI) { + /* Prototype only */ + NextToken (); + } else if (CurTok.Tok == TOK_LCURLY) { + /* ISO C: The type category in a function definition cannot be + ** inherited from a typedef. + */ + if (IsTypeFunc (Spec.Type) && TypeCmp (Sym->Type, Spec.Type).C >= TC_EQUAL) { + Error ("Function cannot be defined with a typedef"); + } else if (comma) { + Error ("';' expected after top level declarator"); } + + /* Parse the function body anyways */ + NewFunc (Sym, FuncDef); + + /* Make sure we aren't omitting any work */ + CheckDeferredOpAllDone (); } } else { diff --git a/test/err/bug2020-definition.c b/test/err/bug2020-definition.c new file mode 100644 index 000000000..7443e3a9a --- /dev/null +++ b/test/err/bug2020-definition.c @@ -0,0 +1,6 @@ +/* Bug #2020 - ISO/IEC 9899:1999 (E), 6.9.1 footnote 137: +** "The intent is that the type category in a function definition cannot be inherited from a typedef" + */ + +typedef void F(void); +F c { } /* Should fail */ diff --git a/test/val/bug2020-ok.c b/test/val/bug2020-ok.c new file mode 100644 index 000000000..6c52a9498 --- /dev/null +++ b/test/val/bug2020-ok.c @@ -0,0 +1,16 @@ +/* Bug #2020 - Right cases */ + +typedef int F(void); // type F is "function with no parameters returning int" + +F f, g; // f and g both have type compatible with F +int f(void) { return 0; } // RIGHT: f has type compatible with F +int g() { return 0; } // RIGHT: g has type compatible with F +F *e(void) { return 0; } // e returns a pointer to a function +F *((h))(void) { return 0; } // similar: parentheses irrelevant +int (*fp)(void); // fp points to a function that has type F +F *Fp; // Fp points to a function that has type + +int main(void) +{ + return 0; +}