static void free_declarator(struct cdecl_declarator *x)
{
struct cdecl_declarator *p;
+
while (x) {
- p = x->next;
+ p = x->child;
+
switch (x->type) {
case CDECL_DECL_NULL:
break;
assert(0);
}
- free_declarator(x->child);
free(x);
x = p;
}
}
-static void free_decl(struct cdecl *decl)
+static void free_decl(struct cdecl *x)
{
- free_declspec(decl->specifiers);
- free_declarator(decl->declarators);
- free(decl);
+ struct cdecl *p;
+
+ while (x) {
+ p = x->next;
+
+ /* The specifiers may be shared by an entire chain. */
+ if (!p || p->specifiers != x->specifiers)
+ free_declspec(x->specifiers);
+
+ free_declarator(x->declarators);
+ free(x);
+ x = p;
+ }
}
void cdecl_free(struct cdecl *decl)
{
- if (decl)
- free_decl(decl);
+ free_decl(decl);
}
%}
%type <declspec> declspec_notype declspec_noid typespec_noid typespec
%type <declspec> qualifier qualifiers
%type <declspec> declspecs declspecs_noid
-%type <declarator> direct_declarator declarator declarators pointer array
-%type <decl> declaration
+%type <declarator> direct_declarator declarator pointer array
+%type <decl> declaration declarators declarator_wrap
%%
};
declaration: declspecs declarators T_SEMICOLON {
- ALLOC_STRUCT($$, struct cdecl,
- .specifiers = $1,
- .declarators = $2);
+ $$ = $2;
+
+ for (struct cdecl *i = $$; i; i = i->next)
+ i->specifiers = $1;
};
declspecs: declspec_notype declspecs {
$$->next = $1;
}
-declarators: declarator | declarator T_COMMA declarators {
+declarators: declarator_wrap | declarator_wrap T_COMMA declarators {
$$ = $1;
$$->next = $3;
-};
+}
+
+declarator_wrap: declarator {
+ ALLOC_STRUCT($$, struct cdecl, .declarators = $1);
+}
declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO; }
| T_TYPEDEF { $$ = CDECL_STOR_TYPEDEF; }