Print this page
new smatch

*** 32,41 **** --- 32,42 ---- #include <ctype.h> #include <unistd.h> #include <fcntl.h> #include <limits.h> + #include "evaluate.h" #include "lib.h" #include "allocate.h" #include "parse.h" #include "token.h" #include "symbol.h"
*** 42,54 **** --- 43,68 ---- #include "target.h" #include "expression.h" struct symbol *current_fn; + struct ident bad_address_space = { .len = 6, .name = "bad AS", }; + static struct symbol *degenerate(struct expression *expr); static struct symbol *evaluate_symbol(struct symbol *sym); + static inline int valid_expr_type(struct expression *expr) + { + return expr && valid_type(expr->ctype); + } + + static inline int valid_subexpr_type(struct expression *expr) + { + return valid_expr_type(expr->left) + && valid_expr_type(expr->right); + } + static struct symbol *evaluate_symbol_expression(struct expression *expr) { struct expression *addr; struct symbol *sym = expr->symbol; struct symbol *base_type;
*** 194,211 **** { return orig->bit_size == new->bit_size && orig->bit_offset == new->bit_offset; } ! static struct symbol *base_type(struct symbol *node, unsigned long *modp, unsigned long *asp) { ! unsigned long mod, as; - mod = 0; as = 0; while (node) { mod |= node->ctype.modifiers; ! as |= node->ctype.as; if (node->type == SYM_NODE) { node = node->ctype.base_type; continue; } break; --- 208,225 ---- { return orig->bit_size == new->bit_size && orig->bit_offset == new->bit_offset; } ! static struct symbol *base_type(struct symbol *node, unsigned long *modp, struct ident **asp) { ! unsigned long mod = 0; ! struct ident *as = NULL; while (node) { mod |= node->ctype.modifiers; ! combine_address_space(node->pos, &as, node->ctype.as); if (node->type == SYM_NODE) { node = node->ctype.base_type; continue; } break;
*** 216,226 **** } static int is_same_type(struct expression *expr, struct symbol *new) { struct symbol *old = expr->ctype; ! unsigned long oldmod, newmod, oldas, newas; old = base_type(old, &oldmod, &oldas); new = base_type(new, &newmod, &newas); /* Same base type, same address space? */ --- 230,241 ---- } static int is_same_type(struct expression *expr, struct symbol *new) { struct symbol *old = expr->ctype; ! unsigned long oldmod, newmod; ! struct ident *oldas, *newas; old = base_type(old, &oldmod, &oldas); new = base_type(new, &newmod, &newas); /* Same base type, same address space? */
*** 391,409 **** return type->type == SYM_ARRAY && is_byte_type(type->ctype.base_type); } static struct symbol *bad_expr_type(struct expression *expr) { - sparse_error(expr->pos, "incompatible types for operation (%s)", show_special(expr->op)); switch (expr->type) { case EXPR_BINOP: case EXPR_COMPARE: info(expr->pos, " left side has type %s", show_typename(expr->left->ctype)); info(expr->pos, " right side has type %s", show_typename(expr->right->ctype)); break; case EXPR_PREOP: case EXPR_POSTOP: info(expr->pos, " argument has type %s", show_typename(expr->unop->ctype)); break; default: break; } --- 406,429 ---- return type->type == SYM_ARRAY && is_byte_type(type->ctype.base_type); } static struct symbol *bad_expr_type(struct expression *expr) { switch (expr->type) { case EXPR_BINOP: case EXPR_COMPARE: + if (!valid_subexpr_type(expr)) + break; + sparse_error(expr->pos, "incompatible types for operation (%s)", show_special(expr->op)); info(expr->pos, " left side has type %s", show_typename(expr->left->ctype)); info(expr->pos, " right side has type %s", show_typename(expr->right->ctype)); break; case EXPR_PREOP: case EXPR_POSTOP: + if (!valid_expr_type(expr->unop)) + break; + sparse_error(expr->pos, "incompatible types for operation (%s)", show_special(expr->op)); info(expr->pos, " argument has type %s", show_typename(expr->unop->ctype)); break; default: break; }
*** 636,651 **** return ctype; } static void examine_fn_arguments(struct symbol *fn); ! #define MOD_IGN (MOD_VOLATILE | MOD_CONST | MOD_PURE) const char *type_difference(struct ctype *c1, struct ctype *c2, unsigned long mod1, unsigned long mod2) { ! unsigned long as1 = c1->as, as2 = c2->as; struct symbol *t1 = c1->base_type; struct symbol *t2 = c2->base_type; int move1 = 1, move2 = 1; mod1 |= c1->modifiers; mod2 |= c2->modifiers; --- 656,671 ---- return ctype; } static void examine_fn_arguments(struct symbol *fn); ! #define MOD_IGN (MOD_QUALIFIER | MOD_PURE) const char *type_difference(struct ctype *c1, struct ctype *c2, unsigned long mod1, unsigned long mod2) { ! struct ident *as1 = c1->as, *as2 = c2->as; struct symbol *t1 = c1->base_type; struct symbol *t2 = c2->base_type; int move1 = 1, move2 = 1; mod1 |= c1->modifiers; mod2 |= c2->modifiers;
*** 659,677 **** * FIXME! Collect alignment and context too here! */ if (move1) { if (t1 && t1->type != SYM_PTR) { mod1 |= t1->ctype.modifiers; ! as1 |= t1->ctype.as; } move1 = 0; } if (move2) { if (t2 && t2->type != SYM_PTR) { mod2 |= t2->ctype.modifiers; ! as2 |= t2->ctype.as; } move2 = 0; } if (t1 == t2) --- 679,697 ---- * FIXME! Collect alignment and context too here! */ if (move1) { if (t1 && t1->type != SYM_PTR) { mod1 |= t1->ctype.modifiers; ! combine_address_space(t1->pos, &as1, t1->ctype.as); } move1 = 0; } if (move2) { if (t2 && t2->type != SYM_PTR) { mod2 |= t2->ctype.modifiers; ! combine_address_space(t2->pos, &as2, t2->ctype.as); } move2 = 0; } if (t1 == t2)
*** 845,857 **** val->ctype = size_t_ctype; val->value = value; if (value & (value-1)) { ! if (Wptr_subtraction_blows) warning(expr->pos, "potentially expensive pointer subtraction"); } sub->op = '-'; sub->ctype = ssize_t_ctype; sub->left = l; sub->right = r; --- 865,879 ---- val->ctype = size_t_ctype; val->value = value; if (value & (value-1)) { ! if (Wptr_subtraction_blows) { warning(expr->pos, "potentially expensive pointer subtraction"); + info(expr->pos, " '%s' has a non-power-of-2 size: %lu", show_typename(lbase), value); } + } sub->op = '-'; sub->ctype = ssize_t_ctype; sub->left = l; sub->right = r;
*** 875,901 **** if (!iterator && expr->type == EXPR_ASSIGNMENT && expr->op == '=') warning(expr->pos, "assignment expression in conditional"); ctype = evaluate_expression(expr); ! if (ctype) { if (is_safe_type(ctype)) warning(expr->pos, "testing a 'safe expression'"); if (is_func_type(ctype)) { if (Waddress) warning(expr->pos, "the address of %s will always evaluate as true", "a function"); } else if (is_array_type(ctype)) { if (Waddress) warning(expr->pos, "the address of %s will always evaluate as true", "an array"); } else if (!is_scalar_type(ctype)) { ! sparse_error(expr->pos, "incorrect type in conditional"); info(expr->pos, " got %s", show_typename(ctype)); ! ctype = NULL; } - } - ctype = degenerate(expr); return ctype; } static struct symbol *evaluate_logical(struct expression *expr) { --- 897,923 ---- if (!iterator && expr->type == EXPR_ASSIGNMENT && expr->op == '=') warning(expr->pos, "assignment expression in conditional"); ctype = evaluate_expression(expr); ! if (!valid_type(ctype)) ! return NULL; if (is_safe_type(ctype)) warning(expr->pos, "testing a 'safe expression'"); if (is_func_type(ctype)) { if (Waddress) warning(expr->pos, "the address of %s will always evaluate as true", "a function"); } else if (is_array_type(ctype)) { if (Waddress) warning(expr->pos, "the address of %s will always evaluate as true", "an array"); } else if (!is_scalar_type(ctype)) { ! sparse_error(expr->pos, "incorrect type in conditional (non-scalar type)"); info(expr->pos, " got %s", show_typename(ctype)); ! return NULL; } + ctype = degenerate(expr); return ctype; } static struct symbol *evaluate_logical(struct expression *expr) {
*** 1003,1019 **** else if (op == SPECIAL_GTE) op = SPECIAL_UNSIGNED_GTE; return op; } static inline int is_null_pointer_constant(struct expression *e) { if (e->ctype == &null_ctype) ! return 1; if (!(e->flags & CEF_ICE)) ! return 0; ! return is_zero_constant(e) ? 2 : 0; } static struct symbol *evaluate_compare(struct expression *expr) { struct expression *left = expr->left, *right = expr->right; --- 1025,1047 ---- else if (op == SPECIAL_GTE) op = SPECIAL_UNSIGNED_GTE; return op; } + enum null_constant_type { + NON_NULL, + NULL_PTR, + NULL_ZERO, + }; + static inline int is_null_pointer_constant(struct expression *e) { if (e->ctype == &null_ctype) ! return NULL_PTR; if (!(e->flags & CEF_ICE)) ! return NON_NULL; ! return is_zero_constant(e) ? NULL_ZERO : NON_NULL; } static struct symbol *evaluate_compare(struct expression *expr) { struct expression *left = expr->left, *right = expr->right;
*** 1055,1067 **** /* equality comparisons can be with null pointer constants */ if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) { int is_null1 = is_null_pointer_constant(left); int is_null2 = is_null_pointer_constant(right); ! if (is_null1 == 2) bad_null(left); ! if (is_null2 == 2) bad_null(right); if (is_null1 && is_null2) { int positive = expr->op == SPECIAL_EQUAL; expr->type = EXPR_VALUE; expr->value = positive; --- 1083,1095 ---- /* equality comparisons can be with null pointer constants */ if (expr->op == SPECIAL_EQUAL || expr->op == SPECIAL_NOTEQUAL) { int is_null1 = is_null_pointer_constant(left); int is_null2 = is_null_pointer_constant(right); ! if (is_null1 == NULL_ZERO) bad_null(left); ! if (is_null2 == NULL_ZERO) bad_null(right); if (is_null1 && is_null2) { int positive = expr->op == SPECIAL_EQUAL; expr->type = EXPR_VALUE; expr->value = positive;
*** 1102,1112 **** target_qualifiers(rtype), target_qualifiers(ltype)); if (!typediff) goto OK; ! expression_error(expr, "incompatible types in comparison expression (%s)", typediff); return NULL; OK: /* the result is int [6.5.8(6), 6.5.9(3)]*/ expr->ctype = &int_ctype; --- 1130,1142 ---- target_qualifiers(rtype), target_qualifiers(ltype)); if (!typediff) goto OK; ! expression_error(expr, "incompatible types in comparison expression (%s):", typediff); ! info(expr->pos, " %s", show_typename(ltype)); ! info(expr->pos, " %s", show_typename(rtype)); return NULL; OK: /* the result is int [6.5.8(6), 6.5.9(3)]*/ expr->ctype = &int_ctype;
*** 1120,1130 **** * test in the expression. But since promotion is "safe" * for testing, that's OK. */ static struct symbol *evaluate_conditional_expression(struct expression *expr) { ! struct expression **true; struct symbol *ctype, *ltype, *rtype, *lbase, *rbase; int lclass, rclass; const char * typediff; int qual; --- 1150,1160 ---- * test in the expression. But since promotion is "safe" * for testing, that's OK. */ static struct symbol *evaluate_conditional_expression(struct expression *expr) { ! struct expression **cond; struct symbol *ctype, *ltype, *rtype, *lbase, *rbase; int lclass, rclass; const char * typediff; int qual;
*** 1134,1153 **** return NULL; ctype = degenerate(expr->conditional); rtype = degenerate(expr->cond_false); ! true = &expr->conditional; ltype = ctype; if (expr->cond_true) { if (!evaluate_expression(expr->cond_true)) return NULL; ltype = degenerate(expr->cond_true); ! true = &expr->cond_true; } ! expr->flags = (expr->conditional->flags & (*true)->flags & expr->cond_false->flags & ~CEF_CONST_MASK); /* * A conditional operator yields a particular constant * expression type only if all of its three subexpressions are * of that type [6.6(6), 6.6(8)]. --- 1164,1183 ---- return NULL; ctype = degenerate(expr->conditional); rtype = degenerate(expr->cond_false); ! cond = &expr->conditional; ltype = ctype; if (expr->cond_true) { if (!evaluate_expression(expr->cond_true)) return NULL; ltype = degenerate(expr->cond_true); ! cond = &expr->cond_true; } ! expr->flags = (expr->conditional->flags & (*cond)->flags & expr->cond_false->flags & ~CEF_CONST_MASK); /* * A conditional operator yields a particular constant * expression type only if all of its three subexpressions are * of that type [6.6(6), 6.6(8)].
*** 1159,1199 **** * However, as an extension, if the condition is any constant * expression, and the true and false expressions are both * address constants, mark the result as an address constant. */ if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) ! expr->flags = (*true)->flags & expr->cond_false->flags & ~CEF_CONST_MASK; lclass = classify_type(ltype, &ltype); rclass = classify_type(rtype, &rtype); if (lclass & rclass & TYPE_NUM) { ! ctype = usual_conversions('?', *true, expr->cond_false, lclass, rclass, ltype, rtype); ! *true = cast_to(*true, ctype); expr->cond_false = cast_to(expr->cond_false, ctype); goto out; } if ((lclass | rclass) & TYPE_PTR) { ! int is_null1 = is_null_pointer_constant(*true); int is_null2 = is_null_pointer_constant(expr->cond_false); if (is_null1 && is_null2) { ! *true = cast_to(*true, &ptr_ctype); expr->cond_false = cast_to(expr->cond_false, &ptr_ctype); ctype = &ptr_ctype; goto out; } if (is_null1 && (rclass & TYPE_PTR)) { ! if (is_null1 == 2) ! bad_null(*true); ! *true = cast_to(*true, rtype); ctype = rtype; goto out; } if (is_null2 && (lclass & TYPE_PTR)) { ! if (is_null2 == 2) bad_null(expr->cond_false); expr->cond_false = cast_to(expr->cond_false, ltype); ctype = ltype; goto out; } --- 1189,1229 ---- * However, as an extension, if the condition is any constant * expression, and the true and false expressions are both * address constants, mark the result as an address constant. */ if (expr->conditional->flags & (CEF_ACE | CEF_ADDR)) ! expr->flags = (*cond)->flags & expr->cond_false->flags & ~CEF_CONST_MASK; lclass = classify_type(ltype, &ltype); rclass = classify_type(rtype, &rtype); if (lclass & rclass & TYPE_NUM) { ! ctype = usual_conversions('?', *cond, expr->cond_false, lclass, rclass, ltype, rtype); ! *cond = cast_to(*cond, ctype); expr->cond_false = cast_to(expr->cond_false, ctype); goto out; } if ((lclass | rclass) & TYPE_PTR) { ! int is_null1 = is_null_pointer_constant(*cond); int is_null2 = is_null_pointer_constant(expr->cond_false); if (is_null1 && is_null2) { ! *cond = cast_to(*cond, &ptr_ctype); expr->cond_false = cast_to(expr->cond_false, &ptr_ctype); ctype = &ptr_ctype; goto out; } if (is_null1 && (rclass & TYPE_PTR)) { ! if (is_null1 == NULL_ZERO) ! bad_null(*cond); ! *cond = cast_to(*cond, rtype); ctype = rtype; goto out; } if (is_null2 && (lclass & TYPE_PTR)) { ! if (is_null2 == NULL_ZERO) bad_null(expr->cond_false); expr->cond_false = cast_to(expr->cond_false, ltype); ctype = ltype; goto out; }
*** 1238,1248 **** goto out; } typediff = "different base types"; Err: ! expression_error(expr, "incompatible types in conditional expression (%s)", typediff); /* * if the condition is constant, the type is in fact known * so use it, as gcc & clang do. */ switch (expr_truth_value(expr->conditional)) { --- 1268,1280 ---- goto out; } typediff = "different base types"; Err: ! expression_error(expr, "incompatible types in conditional expression (%s):", typediff); ! info(expr->pos, " %s", show_typename(ltype)); ! info(expr->pos, " %s", show_typename(rtype)); /* * if the condition is constant, the type is in fact known * so use it, as gcc & clang do. */ switch (expr_truth_value(expr->conditional)) {
*** 1264,1274 **** struct symbol *sym = alloc_symbol(ctype->pos, SYM_PTR); *sym = *ctype; sym->ctype.modifiers |= qual; ctype = sym; } ! *true = cast_to(*true, ctype); expr->cond_false = cast_to(expr->cond_false, ctype); goto out; } /* FP assignments can not do modulo or bit operations */ --- 1296,1306 ---- struct symbol *sym = alloc_symbol(ctype->pos, SYM_PTR); *sym = *ctype; sym->ctype.modifiers |= qual; ctype = sym; } ! *cond = cast_to(*cond, ctype); expr->cond_false = cast_to(expr->cond_false, ctype); goto out; } /* FP assignments can not do modulo or bit operations */
*** 1304,1313 **** --- 1336,1350 ---- /* allowed assignments unfoul */ if (sclass & TYPE_FOULED && unfoul(s) == t) goto Cast; if (!restricted_value(expr->right, t)) return 1; + } else if (op == SPECIAL_SHR_ASSIGN || op == SPECIAL_SHL_ASSIGN) { + // shifts do integer promotions, but that's it. + unrestrict(expr->right, sclass, &s); + target = integer_promotion(s); + goto Cast; } else if (!(sclass & TYPE_RESTRICT)) goto usual; /* source and target would better be identical restricted */ if (t == s) return 1;
*** 1392,1402 **** unsigned long mod1, mod2; struct symbol *b1, *b2; // NULL pointer is always OK int is_null = is_null_pointer_constant(*rp); if (is_null) { ! if (is_null == 2) bad_null(*rp); goto Cast; } if (!(sclass & TYPE_PTR)) { *typediff = "different base types"; --- 1429,1439 ---- unsigned long mod1, mod2; struct symbol *b1, *b2; // NULL pointer is always OK int is_null = is_null_pointer_constant(*rp); if (is_null) { ! if (is_null == NULL_ZERO) bad_null(*rp); goto Cast; } if (!(sclass & TYPE_PTR)) { *typediff = "different base types";
*** 1542,1552 **** } static struct symbol *evaluate_assignment(struct expression *expr) { struct expression *left = expr->left; - struct expression *where = expr; struct symbol *ltype; if (!lvalue_expression(left)) { expression_error(expr, "not an lvalue"); return NULL; --- 1579,1588 ----
*** 1556,1566 **** if (expr->op != '=') { if (!evaluate_assign_op(expr)) return NULL; } else { ! if (!compatible_assignment_types(where, ltype, &expr->right, "assignment")) return NULL; } evaluate_assign_to(left, ltype); --- 1592,1602 ---- if (expr->op != '=') { if (!evaluate_assign_op(expr)) return NULL; } else { ! if (!compatible_assignment_types(expr, ltype, &expr->right, "assignment")) return NULL; } evaluate_assign_to(left, ltype);
*** 1583,1597 **** ptr = alloc_symbol(s->pos, SYM_PTR); if (arg->type == SYM_ARRAY) ptr->ctype = arg->ctype; else ptr->ctype.base_type = arg; ! ptr->ctype.as |= s->ctype.as; ptr->ctype.modifiers |= s->ctype.modifiers & MOD_PTRINHERIT; s->ctype.base_type = ptr; ! s->ctype.as = 0; s->ctype.modifiers &= ~MOD_PTRINHERIT; s->bit_size = 0; s->examined = 0; examine_symbol_type(s); break; --- 1619,1633 ---- ptr = alloc_symbol(s->pos, SYM_PTR); if (arg->type == SYM_ARRAY) ptr->ctype = arg->ctype; else ptr->ctype.base_type = arg; ! combine_address_space(s->pos, &ptr->ctype.as, s->ctype.as); ptr->ctype.modifiers |= s->ctype.modifiers & MOD_PTRINHERIT; s->ctype.base_type = ptr; ! s->ctype.as = NULL; s->ctype.modifiers &= ~MOD_PTRINHERIT; s->bit_size = 0; s->examined = 0; examine_symbol_type(s); break;
*** 1601,1611 **** } } } END_FOR_EACH_PTR(s); } ! static struct symbol *convert_to_as_mod(struct symbol *sym, int as, int mod) { /* Take the modifiers of the pointer, and apply them to the member */ mod |= sym->ctype.modifiers; if (sym->ctype.as != as || sym->ctype.modifiers != mod) { struct symbol *newsym = alloc_symbol(sym->pos, SYM_NODE); --- 1637,1647 ---- } } } END_FOR_EACH_PTR(s); } ! static struct symbol *convert_to_as_mod(struct symbol *sym, struct ident *as, int mod) { /* Take the modifiers of the pointer, and apply them to the member */ mod |= sym->ctype.modifiers; if (sym->ctype.as != as || sym->ctype.modifiers != mod) { struct symbol *newsym = alloc_symbol(sym->pos, SYM_NODE);
*** 1633,1648 **** if (sym->ctype.modifiers & MOD_REGISTER) { warning(expr->pos, "taking address of 'register' variable '%s'", show_ident(sym->ident)); sym->ctype.modifiers &= ~MOD_REGISTER; } if (sym->type == SYM_NODE) { ! ptr->ctype.as |= sym->ctype.as; ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } if (degenerate && sym->type == SYM_ARRAY) { ! ptr->ctype.as |= sym->ctype.as; ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } ptr->ctype.base_type = sym; --- 1669,1684 ---- if (sym->ctype.modifiers & MOD_REGISTER) { warning(expr->pos, "taking address of 'register' variable '%s'", show_ident(sym->ident)); sym->ctype.modifiers &= ~MOD_REGISTER; } if (sym->type == SYM_NODE) { ! combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as); ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } if (degenerate && sym->type == SYM_ARRAY) { ! combine_address_space(sym->pos, &ptr->ctype.as, sym->ctype.as); ptr->ctype.modifiers |= sym->ctype.modifiers & MOD_PTRINHERIT; sym = sym->ctype.base_type; } ptr->ctype.base_type = sym;
*** 1774,1791 **** /* Dereferencing a node drops all the node information. */ if (ctype->type == SYM_NODE) ctype = ctype->ctype.base_type; - node = alloc_symbol(expr->pos, SYM_NODE); target = ctype->ctype.base_type; switch (ctype->type) { default: expression_error(expr, "cannot dereference this type"); return NULL; case SYM_PTR: node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER; merge_type(node, ctype); break; case SYM_ARRAY: --- 1810,1831 ---- /* Dereferencing a node drops all the node information. */ if (ctype->type == SYM_NODE) ctype = ctype->ctype.base_type; target = ctype->ctype.base_type; + examine_symbol_type(target); switch (ctype->type) { default: expression_error(expr, "cannot dereference this type"); return NULL; + case SYM_FN: + *expr = *op; + return expr->ctype; case SYM_PTR: + node = alloc_symbol(expr->pos, SYM_NODE); node->ctype.modifiers = target->ctype.modifiers & MOD_SPECIFIER; merge_type(node, ctype); break; case SYM_ARRAY:
*** 1799,1808 **** --- 1839,1849 ---- /* * When an array is dereferenced, we need to pick * up the attributes of the original node too.. */ + node = alloc_symbol(expr->pos, SYM_NODE); merge_type(node, op->ctype); merge_type(node, ctype); break; }
*** 1912,1921 **** --- 1953,1963 ---- * the same as the postops */ return evaluate_postop(expr); case '!': + ctype = degenerate(expr->unop); expr->flags = expr->unop->flags & ~CEF_CONST_MASK; /* * A logical negation never yields an address constant * [6.6(9)]. */
*** 2019,2030 **** { int offset; struct symbol *ctype, *member; struct expression *deref = expr->deref, *add; struct ident *ident = expr->member; unsigned int mod; - int address_space; if (!evaluate_expression(deref)) return NULL; if (!ident) { expression_error(expr, "bad member name"); --- 2061,2072 ---- { int offset; struct symbol *ctype, *member; struct expression *deref = expr->deref, *add; struct ident *ident = expr->member; + struct ident *address_space; unsigned int mod; if (!evaluate_expression(deref)) return NULL; if (!ident) { expression_error(expr, "bad member name");
*** 2035,2045 **** examine_symbol_type(ctype); address_space = ctype->ctype.as; mod = ctype->ctype.modifiers; if (ctype->type == SYM_NODE) { ctype = ctype->ctype.base_type; ! address_space |= ctype->ctype.as; mod |= ctype->ctype.modifiers; } if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) { expression_error(expr, "expected structure or union"); return NULL; --- 2077,2087 ---- examine_symbol_type(ctype); address_space = ctype->ctype.as; mod = ctype->ctype.modifiers; if (ctype->type == SYM_NODE) { ctype = ctype->ctype.base_type; ! combine_address_space(deref->pos, &address_space, ctype->ctype.as); mod |= ctype->ctype.modifiers; } if (!ctype || (ctype->type != SYM_STRUCT && ctype->type != SYM_UNION)) { expression_error(expr, "expected structure or union"); return NULL;
*** 2172,2193 **** if (Wpointer_arith) warning(expr->pos, "expression using sizeof(void)"); size = bits_in_char; } ! if (size == 1 && is_bool_type(type)) { if (Wsizeof_bool) ! warning(expr->pos, "expression using sizeof bool"); ! size = bits_in_char; } if (is_function(type->ctype.base_type)) { if (Wpointer_arith) warning(expr->pos, "expression using sizeof on a function"); size = bits_in_char; } if ((size < 0) || (size & (bits_in_char - 1))) expression_error(expr, "cannot size expression"); expr->type = EXPR_VALUE; expr->value = bits_to_bytes(size); --- 2214,2267 ---- if (Wpointer_arith) warning(expr->pos, "expression using sizeof(void)"); size = bits_in_char; } ! if (is_bool_type(type)) { if (Wsizeof_bool) ! warning(expr->pos, "expression using sizeof _Bool"); ! size = bits_to_bytes(bits_in_bool) * bits_in_char; } if (is_function(type->ctype.base_type)) { if (Wpointer_arith) warning(expr->pos, "expression using sizeof on a function"); size = bits_in_char; } + if (is_array_type(type) && size < 0) { // VLA, 1-dimension only + struct expression *base, *size; + struct symbol *base_type; + + if (type->type == SYM_NODE) + type = type->ctype.base_type; // strip the SYM_NODE + base_type = get_base_type(type); + if (!base_type) + goto error; + if (base_type->bit_size <= 0) { + base = alloc_expression(expr->pos, EXPR_SIZEOF); + base->cast_type = base_type; + if (!evaluate_sizeof(base)) + goto error; + } else { + base = alloc_expression(expr->pos, EXPR_VALUE); + base->value = bits_to_bytes(base_type->bit_size); + base->ctype = size_t_ctype; + } + size = alloc_expression(expr->pos, EXPR_CAST); + size->cast_type = size_t_ctype; + size->cast_expression = type->array_size; + if (!evaluate_expression(size)) + goto error; + expr->left = size; + expr->right = base; + expr->type = EXPR_BINOP; + expr->op = '*'; + return expr->ctype = size_t_ctype; + } + + error: if ((size < 0) || (size & (bits_in_char - 1))) expression_error(expr, "cannot size expression"); expr->type = EXPR_VALUE; expr->value = bits_to_bytes(size);
*** 2845,2861 **** return flags; } static struct symbol *evaluate_cast(struct expression *expr) { ! struct expression *target = expr->cast_expression; struct symbol *ctype; ! struct symbol *t1, *t2; ! int class1, class2; ! int as1 = 0, as2 = 0; ! if (!target) return NULL; /* * Special case: a cast can be followed by an * initializer, in which case we need to pass --- 2919,2935 ---- return flags; } static struct symbol *evaluate_cast(struct expression *expr) { ! struct expression *source = expr->cast_expression; struct symbol *ctype; ! struct symbol *ttype, *stype; ! int tclass, sclass; ! struct ident *tas = NULL, *sas = NULL; ! if (!source) return NULL; /* * Special case: a cast can be followed by an * initializer, in which case we need to pass
*** 2864,2878 **** * * A more complex case is when the initializer is * dereferenced as part of a post-fix expression. * We need to produce an expression that can be dereferenced. */ ! if (target->type == EXPR_INITIALIZER) { struct symbol *sym = expr->cast_type; struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL); ! sym->initializer = target; evaluate_symbol(sym); addr->ctype = &lazy_ptr_ctype; /* Lazy eval */ addr->symbol = sym; if (sym->ctype.modifiers & MOD_TOPLEVEL) --- 2938,2952 ---- * * A more complex case is when the initializer is * dereferenced as part of a post-fix expression. * We need to produce an expression that can be dereferenced. */ ! if (source->type == EXPR_INITIALIZER) { struct symbol *sym = expr->cast_type; struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL); ! sym->initializer = source; evaluate_symbol(sym); addr->ctype = &lazy_ptr_ctype; /* Lazy eval */ addr->symbol = sym; if (sym->ctype.modifiers & MOD_TOPLEVEL)
*** 2888,2987 **** ctype = examine_symbol_type(expr->cast_type); expr->ctype = ctype; expr->cast_type = ctype; ! evaluate_expression(target); ! degenerate(target); ! class1 = classify_type(ctype, &t1); ! expr->flags = cast_flags(expr, target); /* * You can always throw a value away by casting to * "void" - that's an implicit "force". Note that * the same is _not_ true of "void *". */ ! if (t1 == &void_ctype) goto out; ! if (class1 & (TYPE_COMPOUND | TYPE_FN)) ! warning(expr->pos, "cast to non-scalar"); ! ! t2 = target->ctype; ! if (!t2) { expression_error(expr, "cast from unknown type"); goto out; } ! class2 = classify_type(t2, &t2); - if (class2 & TYPE_COMPOUND) - warning(expr->pos, "cast from non-scalar"); - if (expr->type == EXPR_FORCE_CAST) goto out; /* allowed cast unfouls */ ! if (class2 & TYPE_FOULED) ! t2 = unfoul(t2); ! if (t1 != t2) { ! if ((class1 & TYPE_RESTRICT) && restricted_value(target, t1)) warning(expr->pos, "cast to %s", ! show_typename(t1)); ! if (class2 & TYPE_RESTRICT) { ! if (t1 == &bool_ctype) { ! if (class2 & TYPE_FOULED) warning(expr->pos, "%s degrades to integer", ! show_typename(t2)); } else { warning(expr->pos, "cast from %s", ! show_typename(t2)); } } } ! if (t1 == &ulong_ctype) ! as1 = -1; ! else if (class1 == TYPE_PTR) { ! examine_pointer_target(t1); ! as1 = t1->ctype.as; } ! if (t2 == &ulong_ctype) ! as2 = -1; ! else if (class2 == TYPE_PTR) { ! examine_pointer_target(t2); ! as2 = t2->ctype.as; } ! if (!as1 && as2 > 0) ! warning(expr->pos, "cast removes address space of expression"); ! if (as1 > 0 && as2 > 0 && as1 != as2) ! warning(expr->pos, "cast between address spaces (<asn:%d>-><asn:%d>)", as2, as1); ! if (as1 > 0 && !as2 && ! !is_null_pointer_constant(target) && Wcast_to_as) warning(expr->pos, ! "cast adds address space to expression (<asn:%d>)", as1); ! if (!(t1->ctype.modifiers & MOD_PTRINHERIT) && class1 == TYPE_PTR && ! !as1 && (target->flags & CEF_ICE)) { ! if (t1->ctype.base_type == &void_ctype) { ! if (is_zero_constant(target)) { /* NULL */ expr->type = EXPR_VALUE; expr->ctype = &null_ctype; expr->value = 0; return expr->ctype; } } } ! if (t1 == &bool_ctype) cast_to_bool(expr); out: return ctype; } /* --- 2962,3080 ---- ctype = examine_symbol_type(expr->cast_type); expr->ctype = ctype; expr->cast_type = ctype; ! evaluate_expression(source); ! degenerate(source); ! tclass = classify_type(ctype, &ttype); ! expr->flags = cast_flags(expr, source); /* * You can always throw a value away by casting to * "void" - that's an implicit "force". Note that * the same is _not_ true of "void *". */ ! if (ttype == &void_ctype) goto out; ! stype = source->ctype; ! if (!stype) { expression_error(expr, "cast from unknown type"); goto out; } ! sclass = classify_type(stype, &stype); if (expr->type == EXPR_FORCE_CAST) goto out; + if (tclass & (TYPE_COMPOUND | TYPE_FN)) + warning(expr->pos, "cast to non-scalar"); + + if (sclass & TYPE_COMPOUND) + warning(expr->pos, "cast from non-scalar"); + /* allowed cast unfouls */ ! if (sclass & TYPE_FOULED) ! stype = unfoul(stype); ! if (ttype != stype) { ! if ((tclass & TYPE_RESTRICT) && restricted_value(source, ttype)) warning(expr->pos, "cast to %s", ! show_typename(ttype)); ! if (sclass & TYPE_RESTRICT) { ! if (ttype == &bool_ctype) { ! if (sclass & TYPE_FOULED) warning(expr->pos, "%s degrades to integer", ! show_typename(stype)); } else { warning(expr->pos, "cast from %s", ! show_typename(stype)); } } } ! if ((ttype == &ulong_ctype || ttype == uintptr_ctype) && !Wcast_from_as) ! tas = &bad_address_space; ! else if (tclass == TYPE_PTR) { ! examine_pointer_target(ttype); ! tas = ttype->ctype.as; } ! if ((stype == &ulong_ctype || stype == uintptr_ctype)) ! sas = &bad_address_space; ! else if (sclass == TYPE_PTR) { ! examine_pointer_target(stype); ! sas = stype->ctype.as; } ! if (!tas && valid_as(sas)) ! warning(expr->pos, "cast removes address space '%s' of expression", show_as(sas)); ! if (valid_as(tas) && valid_as(sas) && tas != sas) ! warning(expr->pos, "cast between address spaces (%s -> %s)", show_as(sas), show_as(tas)); ! if (valid_as(tas) && !sas && ! !is_null_pointer_constant(source) && Wcast_to_as) warning(expr->pos, ! "cast adds address space '%s' to expression", show_as(tas)); ! if (!(ttype->ctype.modifiers & MOD_PTRINHERIT) && tclass == TYPE_PTR && ! !tas && (source->flags & CEF_ICE)) { ! if (ttype->ctype.base_type == &void_ctype) { ! if (is_zero_constant(source)) { /* NULL */ expr->type = EXPR_VALUE; expr->ctype = &null_ctype; expr->value = 0; return expr->ctype; } } } ! if (ttype == &bool_ctype) cast_to_bool(expr); + // checks pointers to restricted + while (Wbitwise_pointer && tclass == TYPE_PTR && sclass == TYPE_PTR) { + tclass = classify_type(ttype->ctype.base_type, &ttype); + sclass = classify_type(stype->ctype.base_type, &stype); + if (ttype == stype) + break; + if (!ttype || !stype) + break; + if (ttype == &void_ctype || stype == &void_ctype) + break; + if (tclass & TYPE_RESTRICT) { + warning(expr->pos, "cast to %s", show_typename(ctype)); + break; + } + if (sclass & TYPE_RESTRICT) { + warning(expr->pos, "cast from %s", show_typename(source->ctype)); + break; + } + } out: return ctype; } /*
*** 3181,3213 **** case EXPR_STRING: return evaluate_string(expr); case EXPR_SYMBOL: return evaluate_symbol_expression(expr); case EXPR_BINOP: ! if (!evaluate_expression(expr->left)) return NULL; - if (!evaluate_expression(expr->right)) - return NULL; return evaluate_binop(expr); case EXPR_LOGICAL: return evaluate_logical(expr); case EXPR_COMMA: evaluate_expression(expr->left); if (!evaluate_expression(expr->right)) return NULL; return evaluate_comma(expr); case EXPR_COMPARE: ! if (!evaluate_expression(expr->left)) return NULL; - if (!evaluate_expression(expr->right)) - return NULL; return evaluate_compare(expr); case EXPR_ASSIGNMENT: ! if (!evaluate_expression(expr->left)) return NULL; - if (!evaluate_expression(expr->right)) - return NULL; return evaluate_assignment(expr); case EXPR_PREOP: if (!evaluate_expression(expr->unop)) return NULL; return evaluate_preop(expr); --- 3274,3306 ---- case EXPR_STRING: return evaluate_string(expr); case EXPR_SYMBOL: return evaluate_symbol_expression(expr); case EXPR_BINOP: ! evaluate_expression(expr->left); ! evaluate_expression(expr->right); ! if (!valid_subexpr_type(expr)) return NULL; return evaluate_binop(expr); case EXPR_LOGICAL: return evaluate_logical(expr); case EXPR_COMMA: evaluate_expression(expr->left); if (!evaluate_expression(expr->right)) return NULL; return evaluate_comma(expr); case EXPR_COMPARE: ! evaluate_expression(expr->left); ! evaluate_expression(expr->right); ! if (!valid_subexpr_type(expr)) return NULL; return evaluate_compare(expr); case EXPR_ASSIGNMENT: ! evaluate_expression(expr->left); ! evaluate_expression(expr->right); ! if (!valid_subexpr_type(expr)) return NULL; return evaluate_assignment(expr); case EXPR_PREOP: if (!evaluate_expression(expr->unop)) return NULL; return evaluate_preop(expr);
*** 3258,3272 **** expression_error(expr, "internal front-end error: initializer in expression"); return NULL; case EXPR_SLICE: expression_error(expr, "internal front-end error: SLICE re-evaluated"); return NULL; } return NULL; } ! static void check_duplicates(struct symbol *sym) { int declared = 0; struct symbol *next = sym; int initialized = sym->initializer != NULL; --- 3351,3368 ---- expression_error(expr, "internal front-end error: initializer in expression"); return NULL; case EXPR_SLICE: expression_error(expr, "internal front-end error: SLICE re-evaluated"); return NULL; + case EXPR_ASM_OPERAND: + expression_error(expr, "internal front-end error: ASM_OPERAND evaluated"); + return NULL; } return NULL; } ! void check_duplicates(struct symbol *sym) { int declared = 0; struct symbol *next = sym; int initialized = sym->initializer != NULL;
*** 3289,3299 **** return; } } if (!declared) { unsigned long mod = sym->ctype.modifiers; ! if (mod & (MOD_STATIC | MOD_REGISTER)) return; if (!(mod & MOD_TOPLEVEL)) return; if (!Wdecl) return; --- 3385,3395 ---- return; } } if (!declared) { unsigned long mod = sym->ctype.modifiers; ! if (mod & (MOD_STATIC | MOD_REGISTER | MOD_EXT_VISIBLE)) return; if (!(mod & MOD_TOPLEVEL)) return; if (!Wdecl) return;
*** 3420,3490 **** } static void evaluate_asm_statement(struct statement *stmt) { struct expression *expr; struct symbol *sym; - int state; expr = stmt->asm_string; if (!expr || expr->type != EXPR_STRING) { sparse_error(stmt->pos, "need constant string for inline asm"); return; } ! state = 0; ! FOR_EACH_PTR(stmt->asm_outputs, expr) { ! switch (state) { ! case 0: /* Identifier */ ! state = 1; ! continue; ! case 1: /* Constraint */ ! state = 2; if (!expr || expr->type != EXPR_STRING) { sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string"); ! *THIS_ADDRESS(expr) = NULL; ! continue; ! } verify_output_constraint(expr, expr->string->data); - continue; ! case 2: /* Expression */ ! state = 0; if (!evaluate_expression(expr)) return; if (!lvalue_expression(expr)) warning(expr->pos, "asm output is not an lvalue"); evaluate_assign_to(expr, expr->ctype); ! continue; ! } ! } END_FOR_EACH_PTR(expr); ! state = 0; ! FOR_EACH_PTR(stmt->asm_inputs, expr) { ! switch (state) { ! case 0: /* Identifier */ ! state = 1; ! continue; ! case 1: /* Constraint */ ! state = 2; if (!expr || expr->type != EXPR_STRING) { sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string"); ! *THIS_ADDRESS(expr) = NULL; ! continue; ! } verify_input_constraint(expr, expr->string->data); - continue; ! case 2: /* Expression */ ! state = 0; ! if (!evaluate_expression(expr)) return; ! continue; ! } ! } END_FOR_EACH_PTR(expr); FOR_EACH_PTR(stmt->asm_clobbers, expr) { if (!expr) { sparse_error(stmt->pos, "bad asm clobbers"); return; --- 3516,3569 ---- } static void evaluate_asm_statement(struct statement *stmt) { struct expression *expr; + struct expression *op; struct symbol *sym; expr = stmt->asm_string; if (!expr || expr->type != EXPR_STRING) { sparse_error(stmt->pos, "need constant string for inline asm"); return; } ! FOR_EACH_PTR(stmt->asm_outputs, op) { ! /* Identifier */ ! /* Constraint */ ! expr = op->constraint; if (!expr || expr->type != EXPR_STRING) { sparse_error(expr ? expr->pos : stmt->pos, "asm output constraint is not a string"); ! op->constraint = NULL; ! } else verify_output_constraint(expr, expr->string->data); ! /* Expression */ ! expr = op->expr; if (!evaluate_expression(expr)) return; if (!lvalue_expression(expr)) warning(expr->pos, "asm output is not an lvalue"); evaluate_assign_to(expr, expr->ctype); ! } END_FOR_EACH_PTR(op); ! FOR_EACH_PTR(stmt->asm_inputs, op) { ! /* Identifier */ ! /* Constraint */ ! expr = op->constraint; if (!expr || expr->type != EXPR_STRING) { sparse_error(expr ? expr->pos : stmt->pos, "asm input constraint is not a string"); ! op->constraint = NULL; ! } else verify_input_constraint(expr, expr->string->data); ! /* Expression */ ! if (!evaluate_expression(op->expr)) return; ! } END_FOR_EACH_PTR(op); FOR_EACH_PTR(stmt->asm_clobbers, expr) { if (!expr) { sparse_error(stmt->pos, "bad asm clobbers"); return;
*** 3580,3590 **** static void evaluate_goto_statement(struct statement *stmt) { struct symbol *label = stmt->goto_label; ! if (label && !label->stmt && !lookup_keyword(label->ident, NS_KEYWORD)) sparse_error(stmt->pos, "label '%s' was not declared", show_ident(label->ident)); evaluate_expression(stmt->goto_expression); } --- 3659,3669 ---- static void evaluate_goto_statement(struct statement *stmt) { struct symbol *label = stmt->goto_label; ! if (label && !label->stmt && label->ident && !lookup_keyword(label->ident, NS_KEYWORD)) sparse_error(stmt->pos, "label '%s' was not declared", show_ident(label->ident)); evaluate_expression(stmt->goto_expression); }