]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Fix spacing after pointer qualifiers (again).
authorNick Bowler <nbowler@draconx.ca>
Sun, 14 Jan 2024 05:42:20 +0000 (00:42 -0500)
committerNick Bowler <nbowler@draconx.ca>
Sun, 14 Jan 2024 05:46:50 +0000 (00:46 -0500)
Some renderings of pointer qualifiers have an unwanted trailing space,
for example:

  > type const pointer to array of int
  int (* const )[]

This exact bug was fixed before, more than 10 years ago, but as no test
case was added it took some time to notice the problem when the fix was
inadvertently deleted.  This time, we fix it again, and also add some
test cases to verify the output.

src/declare.c
tests/decl-good.at

index 172c0a9345c398905b1aafcc4b4cd25c8033b438..5c11381d150b92ad20ccfc3f93d4a4d0a56ac8f9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  Render C declarations.
- *  Copyright © 2011, 2021, 2023 Nick Bowler
+ *  Copyright © 2011, 2021, 2023-2024 Nick Bowler
  *
  *  This program is free software: you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -30,35 +30,37 @@ declare_declarator(struct output_state *dst, struct cdecl_declarator *d);
 
 static void declare_decl(struct output_state *dst, struct cdecl *decl)
 {
+       struct cdecl_declarator *d = decl->declarators;
        const char *sep;
 
        sep = cdecl__emit_specs(dst, decl->specifiers, -1);
-       if (decl->declarators->type != CDECL_DECL_NULL)
+       if (d->type != CDECL_DECL_NULL)
                cdecl__emit(dst, sep);
 
-       declare_declarator(dst, decl->declarators);
+       declare_declarator(dst, d);
 }
 
 static void
 declare_postfix_child(struct output_state *dst, struct cdecl_declarator *d)
 {
-       if (d->type == CDECL_DECL_POINTER)
-               cdecl__emit(dst, "(");
+       bool need_parens = (d->type == CDECL_DECL_POINTER);
 
+       if (need_parens) cdecl__emit(dst, "(");
        declare_declarator(dst, d);
-
-       if (d->type == CDECL_DECL_POINTER)
-               cdecl__emit(dst, ")");
+       if (need_parens) cdecl__emit(dst, ")");
 }
 
-static void declare_pointer(struct output_state *dst, struct cdecl_pointer *p)
+static void declare_pointer(struct output_state *dst, struct cdecl_declarator *d)
 {
-       struct cdecl_declspec *q = p->qualifiers;
+       struct cdecl_declspec *q = d->u.pointer.qualifiers;
 
        if (q) {
+               const char *sep;
+
                cdecl__emit(dst, "* ");
-               cdecl__emit_specs(dst, q, -1);
-               cdecl__emit(dst, " ");
+               sep = cdecl__emit_specs(dst, q, -1);
+               if (d->child->type != CDECL_DECL_NULL)
+                       cdecl__emit(dst, sep);
        } else {
                cdecl__emit(dst, "*");
        }
@@ -108,7 +110,7 @@ declare_declarator(struct output_state *dst, struct cdecl_declarator *d)
                        cdecl__emit(dst, d->u.ident);
                        break;
                case CDECL_DECL_POINTER:
-                       declare_pointer(dst, &d->u.pointer);
+                       declare_pointer(dst, d);
                        break;
                /*
                 * Arrays and functions are special: since they are postfix,
index d22675c13f7e0382aa7941826fafa04fda23bd2c..002e4822beb5c82a2c2cb6373204e803b3114a89 100644 (file)
@@ -212,6 +212,17 @@ SIMPLE_DECLS_EXPLAIN(
 SIMPLE_DECLS_EXPLAIN(
   [[int x, y], [m4_n([declare x as int])declare y as int]])
 
+# Check output spacing around qualified pointers
+SIMPLE_DECLS_DECLARE(
+  [[[int (* const)[]]], [type const pointer to array of int]],
+  [[[int (* volatile const)()]],
+    [type volatile const pointer to function returning int]],
+  [[[int (int * restrict const)]],
+    [type function (restrict const pointer to int) returning int]],
+  [[[int * const x]], [declare x as const pointer to int]],
+  [[[int * volatile * restrict x]],
+    [declare x as restrict pointer to volatile pointer to int]])
+
 # Test the simplify command with multiple declarators.  This is the only
 # command in cdecl99 which will print a single C declaration with more than
 # one full declarator.