]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Remove "too many parentheses" error check.
authorNick Bowler <nbowler@draconx.ca>
Thu, 6 Jul 2023 05:59:43 +0000 (01:59 -0400)
committerNick Bowler <nbowler@draconx.ca>
Fri, 7 Jul 2023 00:26:24 +0000 (20:26 -0400)
It is simply not the case that "int ((int))" is invalid.

Since "int (x(int))" declares x as a function returning int, it follows
that "int ((int))" is simply a type name for function returning int.
Likewise, "int (((int)))" is equivalent, etc.

Rejecting these type names is longstanding broken behaviour.  I think
the entire error check can simply be deleted outright, along with its
associated error message.  The bogus negative test cases are replaced
with new positive tests.

Furthermore, rewrite the big comment that suggests this was reasonable
behaviour, replacing it with a (hopefully) better explanation that
covers how this particular case should be interpreted.

src/errmsg.str
src/parse-decl.c
tests/decl-bad.at
tests/decl-good.at

index 60a6500ef31f4314c42f8de5197a627de16355a6..a0bb117bb17c6484c9493882a03c964e04ffa4d0 100644 (file)
@@ -11,7 +11,6 @@
 &CDECL__EBADQUAL      only pointer types can be restrict-qualified
 &CDECL__ENOTFUNC      only function declarations can have function specifiers
 &CDECL__EBADPARAM     invalid function parameter
-&CDECL__EMANYPAREN    too many parentheses
 &CDECL__EVOIDPARAM    void parameter must stand alone
 &CDECL__ERETFUNC      functions cannot return functions
 &CDECL__ERETARRAY     functions cannot return array
index 3137859708b5745d24ec489309efd97a0edfdd69..c3ba32db8b3ed177dccf4873b98f61d16d4494da 100644 (file)
@@ -234,26 +234,33 @@ simplify_functions(struct cdecl_declarator **p, struct cdecl_declarator *d)
 }
 
 /*
- * The parser's bias towards considering things as functions whenever possible
- * makes nested parentheses tricky.  (x) is considered to be part of a function
- * declarator until simplify_functions converts it.  The problem is that
- * (((x))) is not valid as part of a function declarator, but it *is* valid
- * as an identifier enclosed 3 times in parentheses.  This is complicated by
- * the fact that things like (((int))) are not valid anywhere.
+ * The main parser's bias towards considering things as functions whenever
+ * possible makes nested parentheses tricky.  "(x)" is considered to be part
+ * of a function declarator until simplify_functions converts it.  The problem
+ * is that "(((x)))" is not valid as part of a function declarator, but it _is_
+ * valid as either an identifier enclosed thrice in parentheses, or an abstract
+ * function declarator enclosed twice in parentheses.
  *
- * To avoid ambiguities, the parser actually emits a "function" declarator for
- * every pair of parentheses.  The ones that can't reasonably be functions
- * consist of a single "parameter" with no declaration specifiers (note that
- * every valid function parameter will have at least one type specifier).
+ * To avoid ambiguities, the main parser actually returns a function declarator
+ * for every pair of parentheses.  The ones we need to look at consist of a
+ * single parameter with an empty specifier list (noting that every real
+ * function parameter will have at least one type specifier).
  *
- * This pass is to remove these fake functions from the parse tree.  We take
- * care to avoid turning invalid things like ((int)) into valid things like
- * (int) by observing that the only valid function declarators that appear
- * in these "fake" parentheses are those that have a non-null child declarator
- * (for instance, int ((*)(int)) *or* those that will be eliminated by the
- * simplify_functions pass.
+ * There are two cases:
+ *
+ *   - For (), the parser emits a parameter with a lone null declarator.
+ *     This fake parameter simply gets deleted, leaving us with a normal
+ *     function declarator with an empty identifier list.
+ *
+ *   - Otherwise, the parameter's outermost declarator is not null.  The
+ *     function itself is deleted, replaced in the parse tree with the
+ *     fake parameter's declarator.
+ *
+ * Repeating until there no fake parameters, this reduction transforms, for
+ * example, "(((x)))" into "(x)", an abstract function declarator.  The result
+ * is then subject to the function simplification step, which will turn "(x)"
+ * into x (declaring an identifier).
  */
-
 static struct cdecl *fake_function_param(struct cdecl_declarator *d)
 {
        struct cdecl *param;
@@ -273,7 +280,6 @@ static int
 reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
 {
        struct cdecl *param;
-       int fake = 0;
 
        while ((param = fake_function_param(d))) {
                struct cdecl_declarator *decl = param->declarators;
@@ -289,19 +295,12 @@ reduce_parentheses(struct cdecl_declarator **p, struct cdecl_declarator *d)
 
                        param->declarators = d;
                        *p = d = decl;
-                       fake = 1;
                }
 
                cdecl__free(param);
        }
 
        simplify_functions(p, d);
-       if (fake && (*p)->type == CDECL_DECL_FUNCTION) {
-               /* Started with a fake function but ended with a real one. */
-               cdecl__errmsg(CDECL__EMANYPAREN);
-               return -1;
-       }
-
        return 0;
 }
 
index dc21ea112e311fe3cc39b38baf38e4149120d32e..96c54a3f7fce4323440a4cdf770932439e9e4f5e 100644 (file)
@@ -75,11 +75,7 @@ SIMPLE_BADDECL([Reject ... with no formal parameters],
 
 SIMPLE_BADDECL([Reject identifier lists with extra parentheses],
   [explain int f((x))],
-  [explain int f(())],
-  [explain int (())])
-
-SIMPLE_BADDECL([Reject parameter types with extra parentheses],
-  [explain int ((int))])
+  [explain int f(())])
 
 dnl TODO: Find C&V which actually prohibits these "obviously wrong"
 dnl declarations.
index 8acf26a686c102f7b63d28a5de5cc1ece2066285..7cd68dba2553bc8c93d1f6ea32339dcf761fd808 100644 (file)
@@ -95,3 +95,8 @@ SIMPLE_DECLS(
 SIMPLE_DECLS(
   [[int x@<:@@:>@], [declare x as array of int]],
   [[int @<:@@:>@],  [type array of int]])
+
+SIMPLE_DECLS_EXPLAIN(
+  [[int ((int))], [type function (int) returning int], [int (int)]],
+  [[int (x(int))], [declare x as function (int) returning int], [int x(int)]],
+  [[int (())], [type function returning int], [int ()]])