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, <ype);
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, <ype);
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);
}