Print this page
11972 resync smatch
@@ -32,10 +32,11 @@
#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,13 +43,26 @@
#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,18 +208,18 @@
{
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)
+static struct symbol *base_type(struct symbol *node, unsigned long *modp, struct ident **asp)
{
- unsigned long mod, as;
+ unsigned long mod = 0;
+ struct ident *as = NULL;
- mod = 0; as = 0;
while (node) {
mod |= node->ctype.modifiers;
- as |= node->ctype.as;
+ combine_address_space(node->pos, &as, node->ctype.as);
if (node->type == SYM_NODE) {
node = node->ctype.base_type;
continue;
}
break;
@@ -216,11 +230,12 @@
}
static int is_same_type(struct expression *expr, struct symbol *new)
{
struct symbol *old = expr->ctype;
- unsigned long oldmod, newmod, oldas, newas;
+ 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,19 +406,24 @@
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:
+ 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,16 +656,16 @@
return ctype;
}
static void examine_fn_arguments(struct symbol *fn);
-#define MOD_IGN (MOD_VOLATILE | MOD_CONST | MOD_PURE)
+#define MOD_IGN (MOD_QUALIFIER | 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 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,19 +679,19 @@
* FIXME! Collect alignment and context too here!
*/
if (move1) {
if (t1 && t1->type != SYM_PTR) {
mod1 |= t1->ctype.modifiers;
- as1 |= t1->ctype.as;
+ combine_address_space(t1->pos, &as1, t1->ctype.as);
}
move1 = 0;
}
if (move2) {
if (t2 && t2->type != SYM_PTR) {
mod2 |= t2->ctype.modifiers;
- as2 |= t2->ctype.as;
+ combine_address_space(t2->pos, &as2, t2->ctype.as);
}
move2 = 0;
}
if (t1 == t2)
@@ -845,13 +865,15 @@
val->ctype = size_t_ctype;
val->value = value;
if (value & (value-1)) {
- if (Wptr_subtraction_blows)
+ 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,27 +897,27 @@
if (!iterator && expr->type == EXPR_ASSIGNMENT && expr->op == '=')
warning(expr->pos, "assignment expression in conditional");
ctype = evaluate_expression(expr);
- if (ctype) {
+ 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");
+ sparse_error(expr->pos, "incorrect type in conditional (non-scalar type)");
info(expr->pos, " got %s", show_typename(ctype));
- ctype = NULL;
+ return NULL;
}
- }
- ctype = degenerate(expr);
+ ctype = degenerate(expr);
return ctype;
}
static struct symbol *evaluate_logical(struct expression *expr)
{
@@ -1003,17 +1025,23 @@
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 1;
+ return NULL_PTR;
if (!(e->flags & CEF_ICE))
- return 0;
- return is_zero_constant(e) ? 2 : 0;
+ 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,13 +1083,13 @@
/* 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)
+ if (is_null1 == NULL_ZERO)
bad_null(left);
- if (is_null2 == 2)
+ 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,11 +1130,13 @@
target_qualifiers(rtype),
target_qualifiers(ltype));
if (!typediff)
goto OK;
- expression_error(expr, "incompatible types in comparison expression (%s)", typediff);
+ 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,11 +1150,11 @@
* 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 expression **cond;
struct symbol *ctype, *ltype, *rtype, *lbase, *rbase;
int lclass, rclass;
const char * typediff;
int qual;
@@ -1134,20 +1164,20 @@
return NULL;
ctype = degenerate(expr->conditional);
rtype = degenerate(expr->cond_false);
- true = &expr->conditional;
+ cond = &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;
+ cond = &expr->cond_true;
}
- expr->flags = (expr->conditional->flags & (*true)->flags &
+ 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,41 +1189,41 @@
* 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;
+ 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('?', *true, expr->cond_false,
+ ctype = usual_conversions('?', *cond, expr->cond_false,
lclass, rclass, ltype, rtype);
- *true = cast_to(*true, ctype);
+ *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(*true);
+ int is_null1 = is_null_pointer_constant(*cond);
int is_null2 = is_null_pointer_constant(expr->cond_false);
if (is_null1 && is_null2) {
- *true = cast_to(*true, &ptr_ctype);
+ *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 == 2)
- bad_null(*true);
- *true = cast_to(*true, rtype);
+ 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 == 2)
+ if (is_null2 == NULL_ZERO)
bad_null(expr->cond_false);
expr->cond_false = cast_to(expr->cond_false, ltype);
ctype = ltype;
goto out;
}
@@ -1238,11 +1268,13 @@
goto out;
}
typediff = "different base types";
Err:
- expression_error(expr, "incompatible types in conditional expression (%s)", typediff);
+ 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,11 +1296,11 @@
struct symbol *sym = alloc_symbol(ctype->pos, SYM_PTR);
*sym = *ctype;
sym->ctype.modifiers |= qual;
ctype = sym;
}
- *true = cast_to(*true, ctype);
+ *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,10 +1336,15 @@
/* 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,11 +1429,11 @@
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)
+ if (is_null == NULL_ZERO)
bad_null(*rp);
goto Cast;
}
if (!(sclass & TYPE_PTR)) {
*typediff = "different base types";
@@ -1542,11 +1579,10 @@
}
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;
@@ -1556,11 +1592,11 @@
if (expr->op != '=') {
if (!evaluate_assign_op(expr))
return NULL;
} else {
- if (!compatible_assignment_types(where, ltype, &expr->right, "assignment"))
+ if (!compatible_assignment_types(expr, ltype, &expr->right, "assignment"))
return NULL;
}
evaluate_assign_to(left, ltype);
@@ -1583,15 +1619,15 @@
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;
+ 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 = 0;
+ s->ctype.as = NULL;
s->ctype.modifiers &= ~MOD_PTRINHERIT;
s->bit_size = 0;
s->examined = 0;
examine_symbol_type(s);
break;
@@ -1601,11 +1637,11 @@
}
}
} END_FOR_EACH_PTR(s);
}
-static struct symbol *convert_to_as_mod(struct symbol *sym, int as, int mod)
+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,16 +1669,16 @@
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;
+ 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) {
- ptr->ctype.as |= sym->ctype.as;
+ 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,18 +1810,22 @@
/* 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;
+ 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,10 +1839,11 @@
/*
* 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,10 +1953,11 @@
* 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,12 +2061,12 @@
{
int offset;
struct symbol *ctype, *member;
struct expression *deref = expr->deref, *add;
struct ident *ident = expr->member;
+ struct ident *address_space;
unsigned int mod;
- int address_space;
if (!evaluate_expression(deref))
return NULL;
if (!ident) {
expression_error(expr, "bad member name");
@@ -2035,11 +2077,11 @@
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;
+ 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,22 +2214,54 @@
if (Wpointer_arith)
warning(expr->pos, "expression using sizeof(void)");
size = bits_in_char;
}
- if (size == 1 && is_bool_type(type)) {
+ if (is_bool_type(type)) {
if (Wsizeof_bool)
- warning(expr->pos, "expression using sizeof bool");
- size = bits_in_char;
+ 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,17 +2919,17 @@
return flags;
}
static struct symbol *evaluate_cast(struct expression *expr)
{
- struct expression *target = expr->cast_expression;
+ struct expression *source = expr->cast_expression;
struct symbol *ctype;
- struct symbol *t1, *t2;
- int class1, class2;
- int as1 = 0, as2 = 0;
+ struct symbol *ttype, *stype;
+ int tclass, sclass;
+ struct ident *tas = NULL, *sas = NULL;
- if (!target)
+ if (!source)
return NULL;
/*
* Special case: a cast can be followed by an
* initializer, in which case we need to pass
@@ -2864,15 +2938,15 @@
*
* 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) {
+ if (source->type == EXPR_INITIALIZER) {
struct symbol *sym = expr->cast_type;
struct expression *addr = alloc_expression(expr->pos, EXPR_SYMBOL);
- sym->initializer = target;
+ sym->initializer = source;
evaluate_symbol(sym);
addr->ctype = &lazy_ptr_ctype; /* Lazy eval */
addr->symbol = sym;
if (sym->ctype.modifiers & MOD_TOPLEVEL)
@@ -2888,100 +2962,119 @@
ctype = examine_symbol_type(expr->cast_type);
expr->ctype = ctype;
expr->cast_type = ctype;
- evaluate_expression(target);
- degenerate(target);
+ evaluate_expression(source);
+ degenerate(source);
- class1 = classify_type(ctype, &t1);
+ tclass = classify_type(ctype, &ttype);
- expr->flags = cast_flags(expr, target);
+ 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 (t1 == &void_ctype)
+ if (ttype == &void_ctype)
goto out;
- if (class1 & (TYPE_COMPOUND | TYPE_FN))
- warning(expr->pos, "cast to non-scalar");
-
- t2 = target->ctype;
- if (!t2) {
+ stype = source->ctype;
+ if (!stype) {
expression_error(expr, "cast from unknown type");
goto out;
}
- class2 = classify_type(t2, &t2);
+ sclass = classify_type(stype, &stype);
- if (class2 & TYPE_COMPOUND)
- warning(expr->pos, "cast from non-scalar");
-
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 (class2 & TYPE_FOULED)
- t2 = unfoul(t2);
+ if (sclass & TYPE_FOULED)
+ stype = unfoul(stype);
- if (t1 != t2) {
- if ((class1 & TYPE_RESTRICT) && restricted_value(target, t1))
+ if (ttype != stype) {
+ if ((tclass & TYPE_RESTRICT) && restricted_value(source, ttype))
warning(expr->pos, "cast to %s",
- show_typename(t1));
- if (class2 & TYPE_RESTRICT) {
- if (t1 == &bool_ctype) {
- if (class2 & TYPE_FOULED)
+ show_typename(ttype));
+ if (sclass & TYPE_RESTRICT) {
+ if (ttype == &bool_ctype) {
+ if (sclass & TYPE_FOULED)
warning(expr->pos, "%s degrades to integer",
- show_typename(t2));
+ show_typename(stype));
} else {
warning(expr->pos, "cast from %s",
- show_typename(t2));
+ show_typename(stype));
}
}
}
- if (t1 == &ulong_ctype)
- as1 = -1;
- else if (class1 == TYPE_PTR) {
- examine_pointer_target(t1);
- as1 = t1->ctype.as;
+ 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 (t2 == &ulong_ctype)
- as2 = -1;
- else if (class2 == TYPE_PTR) {
- examine_pointer_target(t2);
- as2 = t2->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 (!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)
+ 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 to expression (<asn:%d>)", as1);
+ "cast adds address space '%s' to expression", show_as(tas));
- 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)) {
+ 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 (t1 == &bool_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,33 +3274,33 @@
case EXPR_STRING:
return evaluate_string(expr);
case EXPR_SYMBOL:
return evaluate_symbol_expression(expr);
case EXPR_BINOP:
- if (!evaluate_expression(expr->left))
+ evaluate_expression(expr->left);
+ evaluate_expression(expr->right);
+ if (!valid_subexpr_type(expr))
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))
+ evaluate_expression(expr->left);
+ evaluate_expression(expr->right);
+ if (!valid_subexpr_type(expr))
return NULL;
- if (!evaluate_expression(expr->right))
- return NULL;
return evaluate_compare(expr);
case EXPR_ASSIGNMENT:
- if (!evaluate_expression(expr->left))
+ evaluate_expression(expr->left);
+ evaluate_expression(expr->right);
+ if (!valid_subexpr_type(expr))
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);
@@ -3258,15 +3351,18 @@
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;
}
-static void check_duplicates(struct symbol *sym)
+void check_duplicates(struct symbol *sym)
{
int declared = 0;
struct symbol *next = sym;
int initialized = sym->initializer != NULL;
@@ -3289,11 +3385,11 @@
return;
}
}
if (!declared) {
unsigned long mod = sym->ctype.modifiers;
- if (mod & (MOD_STATIC | MOD_REGISTER))
+ if (mod & (MOD_STATIC | MOD_REGISTER | MOD_EXT_VISIBLE))
return;
if (!(mod & MOD_TOPLEVEL))
return;
if (!Wdecl)
return;
@@ -3420,71 +3516,54 @@
}
static void evaluate_asm_statement(struct statement *stmt)
{
struct expression *expr;
+ struct expression *op;
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;
+ FOR_EACH_PTR(stmt->asm_outputs, op) {
+ /* Identifier */
- case 1: /* Constraint */
- state = 2;
+ /* Constraint */
+ expr = op->constraint;
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;
- }
+ op->constraint = NULL;
+ } else
verify_output_constraint(expr, expr->string->data);
- continue;
- case 2: /* Expression */
- state = 0;
+ /* 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);
- continue;
- }
- } END_FOR_EACH_PTR(expr);
+ } END_FOR_EACH_PTR(op);
- state = 0;
- FOR_EACH_PTR(stmt->asm_inputs, expr) {
- switch (state) {
- case 0: /* Identifier */
- state = 1;
- continue;
+ FOR_EACH_PTR(stmt->asm_inputs, op) {
+ /* Identifier */
- case 1: /* Constraint */
- state = 2;
+ /* Constraint */
+ expr = op->constraint;
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;
- }
+ op->constraint = NULL;
+ } else
verify_input_constraint(expr, expr->string->data);
- continue;
- case 2: /* Expression */
- state = 0;
- if (!evaluate_expression(expr))
+ /* Expression */
+ if (!evaluate_expression(op->expr))
return;
- continue;
- }
- } END_FOR_EACH_PTR(expr);
+ } END_FOR_EACH_PTR(op);
FOR_EACH_PTR(stmt->asm_clobbers, expr) {
if (!expr) {
sparse_error(stmt->pos, "bad asm clobbers");
return;
@@ -3580,11 +3659,11 @@
static void evaluate_goto_statement(struct statement *stmt)
{
struct symbol *label = stmt->goto_label;
- if (label && !label->stmt && !lookup_keyword(label->ident, NS_KEYWORD))
+ 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);
}