From: Nick Bowler Date: Sun, 14 Jan 2024 05:42:20 +0000 (-0500) Subject: libcdecl: Fix spacing after pointer qualifiers (again). X-Git-Tag: v1.3~33 X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/commitdiff_plain/d325d75dac5339f0c25b741122cde5698c62f04e libcdecl: Fix spacing after pointer qualifiers (again). 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. --- diff --git a/src/declare.c b/src/declare.c index 172c0a9..5c11381 100644 --- a/src/declare.c +++ b/src/declare.c @@ -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, diff --git a/tests/decl-good.at b/tests/decl-good.at index d22675c..002e482 100644 --- a/tests/decl-good.at +++ b/tests/decl-good.at @@ -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.