]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Replace ALLOC_STRUCT with specialized macros.
authorNick Bowler <nbowler@draconx.ca>
Mon, 24 Jul 2023 23:57:56 +0000 (19:57 -0400)
committerNick Bowler <nbowler@draconx.ca>
Fri, 28 Jul 2023 04:20:58 +0000 (00:20 -0400)
While there is some appeal to this generic "do everything" macro,
it depends on a bunch of modern C syntax (variadic macros, compound
literals, designated initializers) which is not always correctly
implemented.  We've already had to work around at least one compiler
bug in the code directly related to this macro.

Using specialized macros for each kind of allocation works better
on older implementations, and moreover we seem to get more compact
code out of modern ones too, probably because compound literals
initialize all members and we don't always need that.

src/parse.y

index f8c960817a31a671ba3e5bd34b462ed452ed4234..9e547617d228e78d006014c0ccc0822822775638 100644 (file)
        } \
 } while (0)
 
-#define ALLOC_STRUCT(ptr, type, ...) do { \
-       ALLOC(ptr, sizeof (type)); \
-       *(ptr) = (type) { __VA_ARGS__ }; \
+#define ALLOC_FUNCTION(ptr, parameters_, variadic_) do { \
+       ALLOC(ptr, sizeof (struct cdecl_declarator)); \
+       (ptr)->type = CDECL_DECL_FUNCTION; \
+       (ptr)->u.function.parameters = parameters_; \
+       (ptr)->u.function.variadic = variadic_; \
+} while (0)
+
+#define ALLOC_ARRAY(ptr, length_) do { \
+       ALLOC(ptr, sizeof (struct cdecl_declarator)); \
+       (ptr)->type = CDECL_DECL_ARRAY; \
+       (ptr)->u.array.vla = NULL; \
+       (ptr)->u.array.length = length_; \
+} while (0)
+
+#define ALLOC_POINTER(ptr, qualifiers_, child_) do { \
+       ALLOC(ptr, sizeof (struct cdecl_declarator)); \
+       (ptr)->child = child_; \
+       (ptr)->type = CDECL_DECL_POINTER; \
+       (ptr)->u.pointer.qualifiers = qualifiers_; \
+} while (0)
+
+#define ALLOC_DECLSPEC(ptr, type_) do { \
+       ALLOC(ptr, sizeof (struct cdecl_declspec)); \
+       (ptr)->type = type_; \
+       (ptr)->ident = NULL; \
+} while (0)
+
+#define ALLOC_DECL(ptr, specifiers_, declarators_) do { \
+       ALLOC(ptr, sizeof (struct cdecl)); \
+       (ptr)->specifiers = specifiers_; \
+       (ptr)->declarators = declarators_; \
+       (ptr)->next = NULL; \
 } while (0)
 
 /*
@@ -320,7 +349,7 @@ declarators: declarator_wrap | declarator_wrap T_COMMA declarators {
 }
 
 declarator_wrap: declarator {
-       ALLOC_STRUCT($$, struct cdecl, .declarators = $1);
+       ALLOC_DECL($$, NULL, $1);
 }
 
 declspec_simple: T_AUTO
@@ -349,17 +378,9 @@ qualifier_simple: T_CONST
        | T_RESTRICT
        | T_VOLATILE
 
-declspec_notype: qualifier | declspec_simple {
-       ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
-}
-
-typespec_noid: typespec_simple {
-       ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
-}
-
-qualifier: qualifier_simple {
-       ALLOC_STRUCT($$, struct cdecl_declspec, .type = $1);
-}
+declspec_notype: qualifier | declspec_simple { ALLOC_DECLSPEC($$, $1); }
+typespec_noid: typespec_simple { ALLOC_DECLSPEC($$, $1); }
+qualifier: qualifier_simple { ALLOC_DECLSPEC($$, $1); }
 
 typespec: typespec_noid | typespec_tagged T_IDENT {
        /* Compiler should be able to elide this assignment. */
@@ -378,9 +399,7 @@ vla_ident: T_IDENT | T_ASTERISK {
 }
 
 array: T_LBRACKET array_length T_RBRACKET {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_ARRAY,
-               .u.array.length = $2);
+       ALLOC_ARRAY($$, $2);
 } | T_LBRACKET vla_ident T_RBRACKET {
        $$ = &$2->u.declarator;
        $$->type = CDECL_DECL_ARRAY;
@@ -389,18 +408,13 @@ array: T_LBRACKET array_length T_RBRACKET {
 }
 
 parameter: declspecs declarator {
-       ALLOC_STRUCT($$, struct cdecl,
-               .specifiers = $1,
-               .declarators = $2);
+       ALLOC_DECL($$, $1, $2);
 }
 
 varargs: { $$ = false; } | T_COMMA T_ELLIPSIS { $$ = true; }
 
 parameter_type_list: parameter varargs {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_FUNCTION,
-               .u.function.parameters = $1,
-               .u.function.variadic = $2);
+       ALLOC_FUNCTION($$, $1, $2);
 } | parameter T_COMMA parameter_type_list {
        $$ = $3;
        $1->next = $$->u.function.parameters;
@@ -410,22 +424,16 @@ parameter_type_list: parameter varargs {
 parens: T_LPAREN parameter_type_list T_RPAREN {
        $$ = $2;
 } | T_LPAREN declarator_ish T_RPAREN {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_FUNCTION);
-       ALLOC_STRUCT($$->u.function.parameters, struct cdecl,
-               .declarators = $2);
+       struct cdecl *fake_params;
+
+       ALLOC_DECL(fake_params, NULL, $2);
+       ALLOC_FUNCTION($$, fake_params, false);
 }
 
 pointer: T_ASTERISK qualifiers direct_declarator {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_POINTER,
-               .u.pointer.qualifiers = $2,
-               .child = $3);
+       ALLOC_POINTER($$, $2, $3);
 } | T_ASTERISK qualifiers pointer {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_POINTER,
-               .u.pointer.qualifiers = $2,
-               .child = $3);
+       ALLOC_POINTER($$, $2, $3);
 }
 
 declarator: direct_declarator | pointer
@@ -460,9 +468,8 @@ english: T_DECLARE T_IDENT T_AS english_declaration {
  */
 storage_func_specs: %prec T_TYPE { $$ = NULL; }
 storage_func_specs: declspec_simple storage_func_specs {
-       ALLOC_STRUCT($$, struct cdecl_declspec,
-               .type = $1,
-               .next = $2);
+       ALLOC_DECLSPEC($$, $1);
+       $$->next = $2;
 }
 
 type_qual_spec: typespec_noid | qualifier
@@ -485,18 +492,13 @@ post_specs: qualifiers typespec type_qual_specs {
 
 english_declaration: storage_func_specs english_declarator post_specs {
        join_specs($3, $1);
-       ALLOC_STRUCT($$, struct cdecl,
-               .specifiers = $3,
-               .declarators = $2);
+       ALLOC_DECL($$, $3, $2);
 }
 
 english_declarator: {
        $$ = NULLDECL;
 } | english_declarator qualifiers T_POINTER T_TO {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_POINTER,
-               .child = $1,
-               .u.pointer.qualifiers = $2);
+       ALLOC_POINTER($$, $2, $1);
 } | english_declarator english_array {
        $$ = $2;
        $$->child = $1;
@@ -506,18 +508,13 @@ english_declarator: {
 }
 
 english_function: T_FUNCTION T_RETURNING {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_FUNCTION,
-               .u.function.parameters = NULL);
+       ALLOC_FUNCTION($$, NULL, false);
 } | T_FUNCTION T_LPAREN english_parameter_list T_RPAREN T_RETURNING {
        $$ = $3;
 }
 
 english_parameter_list: english_parameter varargs {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_FUNCTION,
-               .u.function.parameters = $1,
-               .u.function.variadic = $2);
+       ALLOC_FUNCTION($$, $1, $2);
 } | english_parameter T_COMMA english_parameter_list {
        $$ = $3;
        $1->next = $$->u.function.parameters;
@@ -552,9 +549,7 @@ null_decl: {
  * by shifting, so long as we have a special-case reduction to handle this.
  */
 english_parameter: english_declaration | typedef_name_qual null_decl {
-       ALLOC_STRUCT($$, struct cdecl,
-               .specifiers = $1,
-               .declarators = $2);
+       ALLOC_DECL($$, $1, $2);
 } | T_IDENT T_AS english_declaration {
        $$ = insert_identifier($3, $1);
 }
@@ -565,9 +560,7 @@ english_array: T_VLA T_ARRAY english_vla T_OF {
        $$->u.array.vla = $$->u.ident;
        $$->u.array.length = 0;
 } | T_ARRAY array_length T_OF {
-       ALLOC_STRUCT($$, struct cdecl_declarator,
-               .type = CDECL_DECL_ARRAY,
-               .u.array.length = $2);
+       ALLOC_ARRAY($$, $2);
 }
 
 array_length: { $$ = 0; }