Merge branch 'more-validations' origin/master
authorMichael Wallner <mike@php.net>
Tue, 16 Feb 2016 15:06:30 +0000 (16:06 +0100)
committerMichael Wallner <mike@php.net>
Tue, 16 Feb 2016 15:06:30 +0000 (16:06 +0100)
src/context_dump.c
src/context_validate.c
src/engine.c
src/libffi.c
src/libjit.c
src/marshal.c
src/parser.h
src/parser.re
src/parser_proc.y
tests/parser/validate001.phpt [new file with mode: 0644]

index 2c6e8c06f8245d5e827aa333fc99477d1b390885..f1386710aa3eebab1d91cb92a7ad54634b4346ab 100644 (file)
@@ -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, ", ...");
                        }
                }
index e34330dee6ad521647169778ae4670df8cccf406..f088b590c6d9b5af62cb8dbef37b70f5b5ab0d78 100644 (file)
@@ -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;
                }
        }
@@ -128,24 +128,23 @@ static inline int locate_decl_type_decl(decls *decls, decl_type *type) {
        return 0;
 }
 
+static inline int validate_decl_nodl(PSI_Data *data, decl *decl);
 static inline int validate_decl_struct(PSI_Data *data, decl_struct *s);
 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:
+static inline int validate_decl_type(PSI_Data *data, decl_type *type, decl_arg *def) {
+       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, type->real.def);
                }
                return 1;
+       }
+
+       switch (type->type) {
        case PSI_T_STRUCT:
                if (!locate_decl_type_struct(data->structs, type)) {
                        return 0;
@@ -165,20 +164,37 @@ static inline int validate_decl_type(PSI_Data *data, decl_type *type) {
                if (!locate_decl_type_decl(data->decls, type)) {
                        return 0;
                }
+               if (!validate_decl_nodl(data, type->real.func)) {
+                       return 0;
+               }
                break;
        }
        return 1;
 }
 static inline int validate_decl_typedef(PSI_Data *data, decl_arg *def) {
-       if (!validate_decl_type(data, def->type)) {
+       if (!validate_decl_type(data, def->type, def)) {
+               const char *pre;
+
+               switch (def->type->type) {
+               case PSI_T_STRUCT:      pre = "struct ";        break;
+               case PSI_T_UNION:       pre = "union ";         break;
+               case PSI_T_ENUM:        pre = "enum ";          break;
+               default:                        pre = "";                       break;
+               }
                data->error(data, def->token, PSI_WARNING,
                        "Type '%s' cannot be aliased to %s'%s'",
-                       def->type->name, def->type->type == PSI_T_STRUCT?"struct ":"",
-                       def->var->name);
+                       def->var->name, pre, def->type->name);
                return 0;
        }
-       if (def->type->type == PSI_T_VOID && def->var->pointer_level) {
-               def->type->type = PSI_T_POINTER;
+       if (def->type->type == PSI_T_VOID) {
+               if (def->var->pointer_level) {
+                       def->type->type = PSI_T_POINTER;
+               } else {
+                       data->error(data, def->token, PSI_WARNING,
+                               "Type '%s' cannot be aliased to 'void'",
+                               def->type->name);
+                       return 0;
+               }
        }
        return 1;
 }
@@ -189,7 +205,7 @@ static inline int validate_constant(PSI_Data *data, constant *c) {
 }
 
 static inline int validate_decl_arg(PSI_Data *data, decl_arg *arg) {
-       if (!validate_decl_type(data, arg->type)) {
+       if (!validate_decl_type(data, arg->type, NULL)) {
                data->error(data, arg->type->token, PSI_WARNING,
                        "Cannot use '%s' as type for '%s'",
                        arg->type->name, arg->var->name);
@@ -233,26 +249,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;
@@ -276,10 +301,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:
@@ -333,10 +358,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:
@@ -374,7 +399,7 @@ static inline int validate_decl_struct(PSI_Data *data, decl_struct *s) {
 
        if (!s->size && !s->args->count) {
                data->error(data, s->token, PSI_WARNING,
-                               "Cannot compute size of empty struct %s",
+                               "Cannot compute size of empty struct '%s'",
                                s->name);
                return 0;
        }
@@ -801,10 +826,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;
                                        }
                                }
@@ -949,7 +974,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;
index aa4feeb87d1e0e5ef66e0cede6d1fe1c76bf2ab3..a4bf0d7aced6d50e3cce84b58bf85914bd204855 100644 (file)
@@ -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;
                }
        }
index 19afda09baa803e8edef148f8742cc5265905194..627c97f5a27e5d01384bd659930af49312c3af74 100644 (file)
@@ -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);
index feb6e3d5e805027ecf047c062caac8cf75f3577e..62540ccbeb5b891a452ff502ee6cbde8f8c16df0 100644 (file)
@@ -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);
index 2ec332953e250ec3a24c989e578d1566d8bda569..ce5cc2441702c75a40bf6438bbbe85f90f0751d2 100644 (file)
@@ -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();
        }
index c9e9f752bb8f8747693229f4b79751f68f7aa1fa..105e974a32efd407f777c734ca39d6e4711e6d1c 100644 (file)
@@ -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;
index 61c328d815bab5f210b772c806f6fc60b9b02736..10279ed7674f52f618a92f0eb8601b6fcb0c926c 100644 (file)
@@ -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> ");
        }
index 8ec585d162200253c8bda828adc888468b8f076d..b46053a108832a148d48b3a0cb9f83978a036ea1 100644 (file)
@@ -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
new file mode 100644 (file)
index 0000000..7a0a862
--- /dev/null
@@ -0,0 +1,99 @@
+--TEST--
+validate types
+--SKIPIF--
+<?php 
+extension_loaded("psi") or die("skip - need ext/psi");
+?>
+--FILE--
+===TEST===
+<?php 
+function validate($check, $psi) {
+       $file = __DIR__."/001.psi";
+       file_put_contents($file, $psi);
+       if ($check !== psi_validate($file)) {
+               printf("Assertion failed!\nExpected: %s\n\n%s\n\n",
+                               $check ? "true" : "false", $psi);
+       }
+}
+
+validate(false, "typedef void foo;");
+validate(true, "typedef void *bar;");
+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; \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,
+<<<PSI
+enum {
+       A,
+       B,
+       C
+}
+PSI
+);
+validate(false,
+<<<PSI
+enum {
+       A,
+       B = A + 2,
+       C = X
+}
+PSI
+);
+
+validate(true,
+<<<PSI
+struct a {
+       int i;
+}
+struct b {
+       long l;
+}
+typedef struct b b;
+union v {
+       struct a a;
+       b b;
+       struct {
+               double d;
+       } s;
+       union {
+               long l;
+               double d;
+       } u;
+}
+PSI
+);
+
+validate(true, "typedef int foo(int bar);");
+validate(true, "typedef int (foo)(int bar);");
+validate(true, "typedef int (*foo)(int bar);");
+validate(true, "typedef int *(*foo)(int bar);");
+validate(false, "typedef int *(*foo)(int *(*bar)(int baz));");
+validate(true, "typedef int *(*bar)(int baz); \ntypedef int *(*foo)(bar bar);");
+validate(true, "typedef int bar(int baz); \ntypedef int *(*foo)(bar bar);");
+
+?>
+===DONE===
+--CLEAN--
+<?php
+@unlink(__DIR__."/001.psi");
+?>
+--EXPECTF--
+===TEST===
+
+Warning: PSI syntax error: Unexpected token ';' in %s001.psi on line 1
+
+Warning: PSI syntax error: Unexpected token 'int' in %s001.psi on line 1
+
+Warning: Type 'bar' cannot be aliased to struct 'foo' in %s001.psi on line 1
+
+Warning: Cannot compute size of empty struct 'a' in %s001.psi on line 1
+
+Warning: Unknown variable 'X' in numeric expression in %s001.psi on line 4
+
+Warning: PSI syntax error: Unexpected token '(' in %s001.psi on line 1
+===DONE===