From b2200987b147fa850c5b001620cb2535b2546b7d Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Tue, 16 Feb 2016 14:19:06 +0100 Subject: [PATCH] made the real decl_type a union --- src/context_dump.c | 16 ++-- src/context_validate.c | 69 +++++++++-------- src/engine.c | 4 +- src/libffi.c | 12 +-- src/libjit.c | 12 +-- src/marshal.c | 4 +- src/parser.h | 35 ++++++--- src/parser.re | 2 +- src/parser_proc.y | 139 ++++++++++++++++++++-------------- tests/parser/validate001.phpt | 13 ++-- 10 files changed, 176 insertions(+), 130 deletions(-) diff --git a/src/context_dump.c b/src/context_dump.c index 2c6e8c0..f138671 100644 --- a/src/context_dump.c +++ b/src/context_dump.c @@ -24,7 +24,7 @@ static inline void dump_decl_type(int fd, decl_type *t, unsigned level) { case PSI_T_STRUCT: dprintf(fd, "struct "); if (!strncmp(t->name, "struct@", sizeof("struct"))) { - dump_struct_args(fd, t->strct->args, level); + dump_struct_args(fd, t->real.strct->args, level); return; } break; @@ -32,7 +32,7 @@ static inline void dump_decl_type(int fd, decl_type *t, unsigned level) { case PSI_T_ENUM: dprintf(fd, "enum "); if (!strncmp(t->name, "enum@", sizeof("enum"))) { - dump_enum_items(fd, t->enm->items, level); + dump_enum_items(fd, t->real.enm->items, level); return; } break; @@ -40,7 +40,7 @@ static inline void dump_decl_type(int fd, decl_type *t, unsigned level) { case PSI_T_UNION: dprintf(fd, "union "); if (!strncmp(t->name, "union@", sizeof("union"))) { - dump_struct_args(fd, t->unn->args, level); + dump_struct_args(fd, t->real.unn->args, level); return; } break; @@ -57,20 +57,20 @@ static inline void dump_decl_var(int fd, decl_var *v) { static inline void dump_decl_arg(int fd, decl_arg *a, unsigned level) { if (a->type->type == PSI_T_FUNCTION) { - dump_decl_type(fd, a->type->func->func->type, level); + dump_decl_type(fd, a->type->real.func->func->type, level); dprintf(fd, " ("); dump_decl_var(fd, a->var); dprintf(fd, ")("); - if (a->type->func->args) { + if (a->type->real.func->args) { size_t j; - for (j = 0; j < a->type->func->args->count; ++j) { + for (j = 0; j < a->type->real.func->args->count; ++j) { if (j) { dprintf(fd, ", "); } - dump_decl_arg(fd, a->type->func->args->args[j], level+1); + dump_decl_arg(fd, a->type->real.func->args->args[j], level+1); } - if (a->type->func->args->varargs) { + if (a->type->real.func->args->varargs) { dprintf(fd, ", ..."); } } diff --git a/src/context_validate.c b/src/context_validate.c index a5d3604..5ad642f 100644 --- a/src/context_validate.c +++ b/src/context_validate.c @@ -46,14 +46,14 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { size_t i; struct psi_std_type *stdtyp; - if (type->real) { + if (type->real.def) { return 1; } if (defs) for (i = 0; i < defs->count; ++i) { decl_arg *def = defs->list[i]; if (def->type->type != type->type && !strcmp(def->var->name, type->name)) { - type->real = def->type; + type->real.def = def; return 1; } } @@ -70,12 +70,12 @@ static inline int locate_decl_type_alias(decl_typedefs *defs, decl_type *type) { static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type) { size_t i; - if (type->strct) { + if (type->real.strct) { return 1; } if (structs) for (i = 0; i < structs->count; ++i) { if (!strcmp(structs->list[i]->name, type->name)) { - type->strct = structs->list[i]; + type->real.strct = structs->list[i]; return 1; } } @@ -85,12 +85,12 @@ static inline int locate_decl_type_struct(decl_structs *structs, decl_type *type static inline int locate_decl_type_union(decl_unions *unions, decl_type *type) { size_t i; - if (type->unn) { + if (type->real.unn) { return 1; } if (unions) for (i = 0; i < unions->count; ++i) { if (!strcmp(unions->list[i]->name, type->name)) { - type->unn = unions->list[i]; + type->real.unn = unions->list[i]; return 1; } } @@ -100,12 +100,12 @@ static inline int locate_decl_type_union(decl_unions *unions, decl_type *type) { static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) { size_t i; - if (type->enm) { + if (type->real.enm) { return 1; } if (enums) for (i = 0; i < enums->count; ++i) { if (!strcmp(enums->list[i]->name, type->name)) { - type->enm = enums->list[i]; + type->real.enm = enums->list[i]; return 1; } } @@ -115,12 +115,12 @@ static inline int locate_decl_type_enum(decl_enums *enums, decl_type *type) { static inline int locate_decl_type_decl(decls *decls, decl_type *type) { size_t i; - if (type->func) { + if (type->real.func) { return 1; } if (decls) for (i = 0; i < decls->count; ++i) { if (!strcmp(decls->list[i]->func->var->name, type->name)) { - type->func = decls->list[i]; + type->real.func = decls->list[i]; return 1; } } @@ -133,19 +133,17 @@ static inline int validate_decl_union(PSI_Data *data, decl_union *u); static inline int validate_decl_enum(PSI_Data *data, decl_enum *e); static inline int validate_decl_type(PSI_Data *data, decl_type *type) { - switch (type->type) { - case PSI_T_CHAR: - case PSI_T_SHORT: - case PSI_T_INT: - case PSI_T_LONG: - case PSI_T_NAME: + if (weak_decl_type(type)) { if (!locate_decl_type_alias(data->defs, type)) { return 0; } - if (type->real) { - return validate_decl_type(data, type->real); + if (type->real.def) { + return validate_decl_type(data, type->real.def->type); } return 1; + } + + switch (type->type) { case PSI_T_STRUCT: if (!locate_decl_type_struct(data->structs, type)) { return 0; @@ -252,26 +250,35 @@ static inline int validate_decl_struct_darg(PSI_Data *data, decl_arg *darg, void /* pre-validate any structs/unions/enums */ switch (real->type) { case PSI_T_STRUCT: - if (current && current == real->strct) { + if (current && current == real->real.strct) { return 1; } - if (!validate_decl_struct(data, real->strct)) { + if (!locate_decl_type_struct(data->structs, real)) { + return 0; + } + if (!validate_decl_struct(data, real->real.strct)) { return 0; } break; case PSI_T_UNION: - if (current && current == real->unn) { + if (current && current == real->real.unn) { return 1; } - if (!validate_decl_union(data, real->unn)) { + if (!locate_decl_type_union(data->unions, real)) { + return 0; + } + if (!validate_decl_union(data, real->real.unn)) { return 0; } break; case PSI_T_ENUM: - if (current && current == real->enm) { + if (current && current == real->real.enm) { return 1; } - if (!validate_decl_enum(data, real->enm)) { + if (!locate_decl_type_enum(data->enums, real)) { + return 0; + } + if (!validate_decl_enum(data, real->real.enm)) { return 0; } break; @@ -295,10 +302,10 @@ static inline size_t sizeof_decl_arg(decl_arg *darg) { } else { switch (real->type) { case PSI_T_UNION: - size = real->unn->size; + size = real->real.unn->size; break; case PSI_T_STRUCT: - size = real->strct->size; + size = real->real.strct->size; break; case PSI_T_ENUM: default: @@ -352,10 +359,10 @@ static inline size_t alignof_decl_type(decl_type *t) { switch (real->type) { case PSI_T_STRUCT: - align = alignof_decl_struct(real->strct); + align = alignof_decl_struct(real->real.strct); break; case PSI_T_UNION: - align = alignof_decl_union(real->unn); + align = alignof_decl_union(real->real.unn); break; case PSI_T_ENUM: default: @@ -820,10 +827,10 @@ static inline int validate_set_value_ex(PSI_Data *data, set_value *set, decl_arg if (!set->outer.set || set->outer.set->inner->vals != set->inner->vals) { for (i = 0; i < set->inner->count; ++i) { decl_var *sub_var = set->inner->vals[i]->vars->vars[0]; - decl_arg *sub_ref = locate_struct_member(ref_type->strct, sub_var); + decl_arg *sub_ref = locate_struct_member(ref_type->real.strct, sub_var); if (sub_ref) { - if (!validate_set_value_ex(data, set->inner->vals[i], sub_ref, ref_type->strct->args)) { + if (!validate_set_value_ex(data, set->inner->vals[i], sub_ref, ref_type->real.strct->args)) { return 0; } } @@ -968,7 +975,7 @@ static inline int validate_let_callback(PSI_Data *data, decl_var *cb_var, let_ca data->error(data, cb_var->token, PSI_WARNING, "Not a function: %s", cb_var->name); return 0; } - cb_func = cb_type->func; + cb_func = cb_type->real.func; for (i = 0; i < cb->args->count; ++i) { if (!validate_set_value(data, cb->args->vals[i], cb_func->args->count, cb_func->args->args, 0)) { return 0; diff --git a/src/engine.c b/src/engine.c index aa4feeb..a4bf0d7 100644 --- a/src/engine.c +++ b/src/engine.c @@ -339,7 +339,7 @@ static inline void psi_clean_array_struct(let_stmt *let, decl_arg *darg) { decl_type *type = real_decl_type(darg->type); if (type->type == PSI_T_STRUCT) { - void **ptr = (void **) ((char *) darg->mem + type->strct->size); + void **ptr = (void **) ((char *) darg->mem + type->real.strct->size); while (*ptr) { efree(*ptr++); @@ -427,7 +427,7 @@ static inline void psi_do_args(impl *impl) { switch (real->type) { case PSI_T_STRUCT: - impl->decl->func->ptr = psi_array_to_struct(real->strct, NULL); + impl->decl->func->ptr = psi_array_to_struct(real->real.strct, NULL); break; } } diff --git a/src/libffi.c b/src/libffi.c index 19afda0..627c97f 100644 --- a/src/libffi.c +++ b/src/libffi.c @@ -271,21 +271,21 @@ static inline ffi_type *psi_ffi_decl_type(decl_type *type) { switch (real->type) { case PSI_T_STRUCT: - if (!real->strct->engine.type) { + if (!real->real.strct->engine.type) { ffi_type *strct = calloc(1, sizeof(ffi_type)); strct->type = FFI_TYPE_STRUCT; strct->size = 0; - strct->elements = psi_ffi_struct_type_elements(real->strct); + strct->elements = psi_ffi_struct_type_elements(real->real.strct); - real->strct->engine.type = strct; - real->strct->engine.dtor = psi_ffi_struct_type_dtor; + real->real.strct->engine.type = strct; + real->real.strct->engine.dtor = psi_ffi_struct_type_dtor; } - return real->strct->engine.type; + return real->real.strct->engine.type; case PSI_T_UNION: - return psi_ffi_decl_arg_type(real->unn->args->args[0]); + return psi_ffi_decl_arg_type(real->real.unn->args->args[0]); default: return psi_ffi_token_type(real->type); diff --git a/src/libjit.c b/src/libjit.c index feb6e3d..62540cc 100644 --- a/src/libjit.c +++ b/src/libjit.c @@ -147,21 +147,21 @@ static inline jit_type_t psi_jit_decl_type(decl_type *type) { switch (real->type) { case PSI_T_STRUCT: - if (!real->strct->engine.type) { + if (!real->real.strct->engine.type) { unsigned count; jit_type_t strct, *fields = NULL; - count = psi_jit_struct_type_elements(real->strct, &fields); + count = psi_jit_struct_type_elements(real->real.strct, &fields); strct = jit_type_create_struct(fields, count, 0); - real->strct->engine.type = strct; - real->strct->engine.dtor = psi_jit_struct_type_dtor; + real->real.strct->engine.type = strct; + real->real.strct->engine.dtor = psi_jit_struct_type_dtor; } - return real->strct->engine.type; + return real->real.strct->engine.type; case PSI_T_UNION: - return psi_jit_decl_arg_type(real->unn->args->args[0]); + return psi_jit_decl_arg_type(real->real.unn->args->args[0]); default: return psi_jit_token_type(real->type); diff --git a/src/marshal.c b/src/marshal.c index 2ec3329..ce5cc24 100644 --- a/src/marshal.c +++ b/src/marshal.c @@ -334,7 +334,7 @@ void psi_from_zval_ex(impl_val **ptr, decl_arg *spec, token_t cast, zval *zv, vo val->ival = zval_get_long(zv); break; case PSI_T_STRUCT: - *tmp = *ptr = psi_array_to_struct(real->strct, HASH_OF(zv)); + *tmp = *ptr = psi_array_to_struct(real->real.strct, HASH_OF(zv)); break; } } @@ -501,7 +501,7 @@ impl_val *psi_let_arrval(impl_val *tmp, decl_type *type, impl_arg *iarg, void ** switch (real->type) { case PSI_T_STRUCT: - *to_free = tmp = psi_array_to_struct(real->strct, arr); + *to_free = tmp = psi_array_to_struct(real->real.strct, arr); break; EMPTY_SWITCH_DEFAULT_CASE(); } diff --git a/src/parser.h b/src/parser.h index c9e9f75..105e974 100644 --- a/src/parser.h +++ b/src/parser.h @@ -66,11 +66,13 @@ typedef struct decl_type { PSI_Token *token; char *name; token_t type; - struct decl_type *real; - struct decl_struct *strct; - struct decl_union *unn; - struct decl_enum *enm; - struct decl *func; + union { + struct decl_arg *def; + struct decl_struct *strct; + struct decl_union *unn; + struct decl_enum *enm; + struct decl *func; + } real; } decl_type; static inline decl_type *init_decl_type(token_t type, const char *name) { @@ -80,11 +82,17 @@ static inline decl_type *init_decl_type(token_t type, const char *name) { return t; } -static inline decl_type *real_decl_type(decl_type *type) { - while (type->real) { - type = type->real; +static inline int weak_decl_type(decl_type *type) { + switch (type->type) { + case PSI_T_CHAR: + case PSI_T_SHORT: + case PSI_T_INT: + case PSI_T_LONG: + case PSI_T_NAME: + return type->type; + default: + return 0; } - return type; } static inline void free_decl(struct decl *decl); @@ -93,7 +101,7 @@ static inline void free_decl_type(decl_type *type) { free(type->token); } if (type->type == PSI_T_FUNCTION) { - free_decl(type->func); + free_decl(type->real.func); } free(type->name); free(type); @@ -185,6 +193,13 @@ static inline void free_decl_arg(decl_arg *arg) { free(arg); } +static inline decl_type *real_decl_type(decl_type *type) { + while (weak_decl_type(type)) { + type = type->real.def->type; + } + return type; +} + typedef struct decl_typedefs { size_t count; decl_arg **list; diff --git a/src/parser.re b/src/parser.re index 61c328d..10279ed 100644 --- a/src/parser.re +++ b/src/parser.re @@ -37,8 +37,8 @@ PSI_Parser *PSI_ParserInit(PSI_Parser *P, const char *filename, psi_error_cb err P->line = 1; P->error = error; P->flags = flags; - P->proc = PSI_ParserProcAlloc(malloc); + if (flags & PSI_PARSER_DEBUG) { PSI_ParserProcTrace(stderr, "PSI> "); } diff --git a/src/parser_proc.y b/src/parser_proc.y index 8ec585d..b46053a 100644 --- a/src/parser_proc.y +++ b/src/parser_proc.y @@ -57,11 +57,22 @@ block ::= impl(impl). { } block ::= decl_typedef(def). { P->defs = add_decl_typedef(P->defs, def); - if (def->type->strct) { - P->structs = add_decl_struct(P->structs, def->type->strct); - } - if (def->type->enm) { - P->enums = add_decl_enum(P->enums, def->type->enm); + switch (def->type->type) { + case PSI_T_STRUCT: + if (def->type->real.strct) { + P->structs = add_decl_struct(P->structs, def->type->real.strct); + } + break; + case PSI_T_UNION: + if (def->type->real.unn) { + P->unions = add_decl_union(P->unions, def->type->real.unn); + } + break; + case PSI_T_ENUM: + if (def->type->real.enm) { + P->enums = add_decl_enum(P->enums, def->type->real.enm); + } + break; } } block ::= constant(constant). { @@ -208,16 +219,16 @@ constant(constant) ::= CONST const_type(type) NSNAME(T) EQUALS impl_def_val(val) %type decl_typedef {decl_arg*} %destructor decl_typedef { - free_decl_arg($$); - if ($$->type->strct) { - free_decl_struct($$->type->strct); - } - if ($$->type->enm) { - free_decl_enum($$->type->enm); + free_decl_arg($$);/* + if ($$->type->real.strct) { + free_decl_struct($$->type->real.strct); } - if ($$->type->func) { - free_decl($$->type->func); + if ($$->type->real.enm) { + free_decl_enum($$->type->real.enm); } + if ($$->type->real.func) { + free_decl($$->type->real.func); + }*/ } decl_typedef(def) ::= TYPEDEF(T) decl_typedef_body(def_) EOS. { def = def_; @@ -225,57 +236,57 @@ decl_typedef(def) ::= TYPEDEF(T) decl_typedef_body(def_) EOS. { } %type decl_typedef_body_ex {decl_arg*} %destructor decl_typedef_body_ex { - free_decl_arg($$); - if ($$->type->strct) { - free_decl_struct($$->type->strct); - } - if ($$->type->enm) { - free_decl_enum($$->type->enm); + free_decl_arg($$);/* + if ($$->type->real.strct) { + free_decl_struct($$->type->real.strct); } - if ($$->type->unn) { - free_decl_union($$->type->unn); + if ($$->type->real.enm) { + free_decl_enum($$->type->real.enm); } - if ($$->type->func) { - free_decl($$->type->func); + if ($$->type->real.unn) { + free_decl_union($$->type->real.unn); } + if ($$->type->real.func) { + free_decl($$->type->real.func); + }*/ } decl_typedef_body_ex(def) ::= struct_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). { def = init_decl_arg(init_decl_type(PSI_T_STRUCT, N->text), var); def->type->token = PSI_TokenCopy(N); - def->type->strct = init_decl_struct(N->text, args); - def->type->strct->token = N; - def->type->strct->align = as.a; - def->type->strct->size = as.s; + def->type->real.strct = init_decl_struct(N->text, args); + def->type->real.strct->token = N; + def->type->real.strct->align = as.a; + def->type->real.strct->size = as.s; } decl_typedef_body_ex(def) ::= union_name(N) align_and_size(as) decl_struct_args_block(args) decl_var(var). { def = init_decl_arg(init_decl_type(PSI_T_UNION, N->text), var); def->type->token = PSI_TokenCopy(N); - def->type->unn = init_decl_union(N->text, args); - def->type->unn->token = N; - def->type->unn->align = as.a; - def->type->unn->size = as.s; + def->type->real.unn = init_decl_union(N->text, args); + def->type->real.unn->token = N; + def->type->real.unn->align = as.a; + def->type->real.unn->size = as.s; } decl_typedef_body_ex(def) ::= decl_enum(e) NAME(ALIAS). { def = init_decl_arg(init_decl_type(PSI_T_ENUM, e->name), init_decl_var(ALIAS->text, 0, 0)); def->var->token = ALIAS; def->type->token = PSI_TokenCopy(e->token); - def->type->enm = e; + def->type->real.enm = e; } %type decl_typedef_body {decl_arg*} %destructor decl_typedef_body { - free_decl_arg($$); - if ($$->type->strct) { - free_decl_struct($$->type->strct); - } - if ($$->type->enm) { - free_decl_enum($$->type->enm); + free_decl_arg($$);/* + if ($$->type->real.strct) { + free_decl_struct($$->type->real.strct); } - if ($$->type->unn) { - free_decl_union($$->type->unn); + if ($$->type->real.enm) { + free_decl_enum($$->type->real.enm); } - if ($$->type->func) { - free_decl($$->type->func); + if ($$->type->real.unn) { + free_decl_union($$->type->real.unn); } + if ($$->type->real.func) { + free_decl($$->type->real.func); + }*/ } decl_typedef_body(def) ::= decl_typedef_body_ex(def_). { def = def_; @@ -288,7 +299,7 @@ decl_typedef_body_fn_args(args) ::= LPAREN decl_args(args_) RPAREN. { decl_typedef_body(def) ::= decl_func(func_) decl_typedef_body_fn_args(args). { def = init_decl_arg(init_decl_type(PSI_T_FUNCTION, func_->var->name), copy_decl_var(func_->var)); def->type->token = PSI_TokenCopy(func_->token); - def->type->func = init_decl(init_decl_abi("default"), func_, args); + def->type->real.func = init_decl(init_decl_abi("default"), func_, args); } decl_typedef_body(def) ::= decl_arg(arg). { def = arg; @@ -330,7 +341,7 @@ decl_typedef_body(def) ::= VOID(T) indirection(decl_i) LPAREN indirection(type_i ); def->var->pointer_level = type_i; def->type->token = PSI_TokenCopy(func_->token); - def->type->func = init_decl(init_decl_abi("default"), func_, args); + def->type->real.func = init_decl(init_decl_abi("default"), func_, args); } decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(type_i) NAME(N) RPAREN decl_typedef_body_fn_args(args). { decl_arg *func_ = init_decl_arg( @@ -347,7 +358,7 @@ decl_typedef_body(def) ::= CONST VOID(T) pointers(decl_i) LPAREN indirection(typ ); def->var->pointer_level = type_i; def->type->token = PSI_TokenCopy(func_->token); - def->type->func = init_decl(init_decl_abi("default"), func_, args); + def->type->real.func = init_decl(init_decl_abi("default"), func_, args); } %type decl_abi {decl_abi*} @@ -397,7 +408,7 @@ decl_typedef_body(def) ::= const_decl_type(type_) indirection(decl_i) LPAREN ind ); def->var->pointer_level = type_i; def->type->token = PSI_TokenCopy(func_->token); - def->type->func = init_decl(init_decl_abi("default"), func_, args); + def->type->real.func = init_decl(init_decl_abi("default"), func_, args); } /* void pointers need a specific rule */ @@ -445,23 +456,35 @@ struct_args(args) ::= struct_args(args_) struct_arg(arg). { %type struct_arg {decl_arg*} %destructor struct_arg { free_decl_arg($$); - if ($$->type->strct) { - free_decl_struct($$->type->strct); + /* + if ($$->type->real.strct) { + free_decl_struct($$->type->real.strct); } - if ($$->type->enm) { - free_decl_enum($$->type->enm); - } - if ($$->type->func) { - free_decl($$->type->func); + if ($$->type->real.enm) { + free_decl_enum($$->type->real.enm); } + if ($$->type->real.func) { + free_decl($$->type->real.func); + }*/ } struct_arg(arg_) ::= decl_typedef_body_ex(def) EOS. { arg_ = def; - if (def->type->strct) { - P->structs = add_decl_struct(P->structs, def->type->strct); - } - if (def->type->enm) { - P->enums = add_decl_enum(P->enums, def->type->enm); + switch (def->type->type) { + case PSI_T_STRUCT: + if (def->type->real.strct) { + P->structs = add_decl_struct(P->structs, def->type->real.strct); + } + break; + case PSI_T_UNION: + if (def->type->real.unn) { + P->unions = add_decl_union(P->unions, def->type->real.unn); + } + break; + case PSI_T_ENUM: + if (def->type->real.enm) { + P->enums = add_decl_enum(P->enums, def->type->real.enm); + } + break; } } struct_arg(arg) ::= decl_arg(arg_) struct_layout(layout_) EOS. { diff --git a/tests/parser/validate001.phpt b/tests/parser/validate001.phpt index f9869a8..b9a9a61 100644 --- a/tests/parser/validate001.phpt +++ b/tests/parser/validate001.phpt @@ -11,7 +11,8 @@ function validate($check, $psi) { $file = __DIR__."/001.psi"; file_put_contents($file, $psi); if ($check !== psi_validate($file)) { - echo "Assertion failed!\n"; + printf("Assertion failed!\nExpected: %s\n\n%s\n\n", + $check ? "true" : "false", $psi); } } @@ -21,9 +22,9 @@ validate(false, "typedef long int;"); validate(true, "typedef long foo;"); validate(false, "typedef struct foo bar;"); validate(true, "typedef struct {int a;} foo;"); -validate(false, "struct a; \n typedef struct a a_t;"); -validate(true, "struct a::(8,8); \n typedef struct a a_t;"); -validate(true, "typedef struct a a_t; \n struct a::(8,8);"); +validate(false, "struct a; \ntypedef struct a a_t;"); +validate(true, "struct a::(8,8); \ntypedef struct a a_t;"); +validate(true, "typedef struct a a_t; \nstruct a::(8,8);"); validate(true, << ===DONE=== -- 2.30.2