Merging the reduce_parentheses and simplify_functions step missed a case
where the function simplification could pull a fake function declarator
up to the current tree position. Continuing the tree traversal will miss
this, leaving the fake parameter in the tree (which is then rejected as
a syntax error later).
The fix is easy enough, just repeat the whole reduction step until no
changes are needed at the current position before continuing traversal.
Add a new test case that targets this behaviour.
* 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).
* 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).
+ *
+ * The whole process is repeated until no more changes are made to the parse
+ * tree, or a syntax error is detected.
*/
static struct cdecl *fake_function_param(struct cdecl_declarator *d)
{
*/
static struct cdecl *fake_function_param(struct cdecl_declarator *d)
{
- while ((param = fake_function_param(d))) {
- struct cdecl_declarator *decl = param->declarators;
- d->u.function.parameters = NULL;
-
- if (decl->type != CDECL_DECL_NULL) {
- if (d->child->type != CDECL_DECL_NULL) {
- /* Found fake parameter on real function. */
- d->u.function.parameters = param;
- cdecl__errmsg(CDECL__EBADPARAM);
- return -1;
+ do {
+ d = *p;
+ while ((param = fake_function_param(d))) {
+ struct cdecl_declarator *decl = param->declarators;
+ d->u.function.parameters = NULL;
+
+ if (decl->type != CDECL_DECL_NULL) {
+ if (d->child->type != CDECL_DECL_NULL) {
+ /* Fake parameter on real function. */
+ d->u.function.parameters = param;
+ cdecl__errmsg(CDECL__EBADPARAM);
+ return -1;
+ }
+
+ param->declarators = d;
+ *p = d = decl;
- param->declarators = d;
- *p = d = decl;
+ } while (simplify_functions(p, d));
- cdecl__free(param);
- }
-
- simplify_functions(p, d);
[[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 ()]])
[[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 ()]])
+
+SIMPLE_DECLS_EXPLAIN(
+ [[int (x())], [declare x as function returning int], [int x()]],
+ [[int ((x)())], [declare x as function returning int], [int x()]])