validate: fix type stack and leaks
[m6w6/ext-psi] / src / types / number.c
index 4cb1f0295153549f318f686d1822619afb9b342b..5e62c62535e8297baaf33c9e2df3e76a2aa658fd 100644 (file)
@@ -74,6 +74,8 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
                exp->data.ival.ldval = *(long double *) num;
                break;
 #endif
+       case PSI_T_NULL:
+               break;
        case PSI_T_QUOTED_CHAR:
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
@@ -86,6 +88,9 @@ struct psi_number *psi_number_init(token_t t, void *num, unsigned flags)
        case PSI_T_FUNCTION:
                exp->data.call = num;
                break;
+       case PSI_T_SIZEOF:
+               exp->data.dtyp = num;
+               break;
        default:
                assert(0);
        }
@@ -117,6 +122,7 @@ struct psi_number *psi_number_copy(struct psi_number *exp)
 #endif
        case PSI_T_ENUM:
        case PSI_T_CONST:
+       case PSI_T_NULL:
                break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
@@ -130,6 +136,9 @@ struct psi_number *psi_number_copy(struct psi_number *exp)
        case PSI_T_FUNCTION:
                num->data.call = psi_cpp_macro_call_copy(num->data.call);
                break;
+       case PSI_T_SIZEOF:
+               num->data.dtyp = psi_decl_type_copy(num->data.dtyp);
+               break;
        default:
                assert(0);
        }
@@ -160,6 +169,7 @@ void psi_number_free(struct psi_number **exp_ptr)
 #endif
                case PSI_T_ENUM:
                case PSI_T_CONST:
+               case PSI_T_NULL:
                        break;
                case PSI_T_FUNCTION:
                        psi_cpp_macro_call_free(&exp->data.call);
@@ -173,6 +183,9 @@ void psi_number_free(struct psi_number **exp_ptr)
                case PSI_T_NAME:
                        psi_decl_var_free(&exp->data.dvar);
                        break;
+               case PSI_T_SIZEOF:
+                       psi_decl_type_free(&exp->data.dtyp);
+                       break;
                default:
                        assert(0);
                }
@@ -218,6 +231,9 @@ void psi_number_dump(int fd, struct psi_number *exp)
                dprintf(fd, "%" PRIldval, exp->data.ival.ldval);
                break;
 #endif
+       case PSI_T_NULL:
+               dprintf(fd, "NULL");
+               break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
        case PSI_T_DEFINE:
@@ -236,6 +252,9 @@ void psi_number_dump(int fd, struct psi_number *exp)
        case PSI_T_NAME:
                psi_decl_var_dump(fd, exp->data.dvar);
                break;
+       case PSI_T_SIZEOF:
+               psi_decl_type_dump(fd, exp->data.dtyp, 0);
+               break;
        default:
                assert(0);
        }
@@ -439,6 +458,9 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
        struct psi_decl_enum *enm;
 
        switch (exp->type) {
+       case PSI_T_NULL:
+               exp->type = PSI_T_UINT8;
+               /* no break */
        case PSI_T_CONST:
        case PSI_T_INT8:
        case PSI_T_UINT8:
@@ -469,11 +491,12 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
                if (exp->data.dvar->arg) {
                        return true;
                }
-               if (psi_decl_var_validate(data, exp->data.dvar, impl ? impl->decl : NULL,
-                               current_let, current_set)) {
+               if (psi_decl_var_validate(data, exp->data.dvar, impl,
+                               impl ? impl->decl : NULL, current_let, current_set)) {
                        return true;
                }
-               if (cb_decl && psi_decl_var_validate(data, exp->data.dvar, cb_decl, NULL, NULL)) {
+               if (cb_decl && psi_decl_var_validate(data, exp->data.dvar,
+                               NULL, cb_decl, NULL, NULL)) {
                        return true;
                }
                data->error(data, exp->token, PSI_WARNING,
@@ -481,6 +504,21 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
                                exp->data.dvar->name);
                return false;
 
+       case PSI_T_SIZEOF:
+               if (psi_decl_type_validate(data, exp->data.dtyp, 0, NULL)) {
+                       struct psi_decl_type *dtyp = exp->data.dtyp;
+
+                       exp->type = PSI_T_UINT64;
+                       exp->data.ival.u64 = psi_decl_type_get_size(dtyp, NULL);
+                       psi_decl_type_free(&dtyp);
+                       return true;
+               } else {
+                       data->error(data, exp->token, PSI_WARNING,
+                                       "Cannot compute sizeof(%s) (%u)",
+                                       exp->data.dtyp->name, exp->data.dtyp->type);
+               }
+               break;
+
        case PSI_T_NSNAME:
                while (psi_plist_get(data->consts, i++, &cnst)) {
                        if (!strcmp(cnst->name, exp->data.numb)) {
@@ -525,7 +563,7 @@ static inline token_t psi_number_eval_constant(struct psi_number *exp,
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIdval, res->dval);
                return PSI_T_DOUBLE;
        default:
-               if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%d)", exp->data.cnst->type->type);
+               if (frame) PSI_DEBUG_PRINT(frame->context, " ?(t=%u)", exp->data.cnst->type->type);
                return 0;
        }
 }
@@ -537,15 +575,27 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
        impl_val *ref;
        struct psi_call_frame_symbol *sym;
        struct psi_decl_type *real;
+       struct psi_decl_var *var;
        size_t size;
 
-       real = psi_decl_type_get_real(exp->data.dvar->arg->type);
-       size = psi_decl_arg_get_size(exp->data.dvar->arg);
-       sym = psi_call_frame_fetch_symbol(frame, exp->data.dvar);
-       ref = deref_impl_val(sym->ptr, exp->data.dvar);
+       var = exp->data.dvar;
+       real = psi_decl_type_get_real(var->arg->type);
+       size = psi_decl_arg_get_size(var->arg);
+       sym = psi_call_frame_fetch_symbol(frame, var);
+       ref = deref_impl_val(sym->ptr, var);
 
        memcpy(res, ref, size);
 
+       if (var->arg->var->pointer_level > var->pointer_level) {
+               switch (SIZEOF_VOID_P) {
+               case 4:
+                       return PSI_T_INT32;
+               case 8:
+                       return PSI_T_INT64;
+               default:
+                       assert(0);
+               }
+       }
        return real->type;
 }
 
@@ -613,6 +663,10 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f
                if (frame) PSI_DEBUG_PRINT(frame->context, " %" PRIi64, res->i64);
                return PSI_T_INT64;
 
+       case PSI_T_NUMBER:
+               res->i64 = atol(exp->data.numb);
+               return PSI_T_INT64;
+
        case PSI_T_CONST:
                return psi_number_eval_constant(exp, res, frame);