summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-03-05 00:23:13 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2019-09-30 02:09:45 +0200
commit2c80708a7c053671c344fc23e561621bdbcbae4d (patch)
tree7cbf46b4a72a7153ced66036081af043c7110922
parentc1d5521fcd0220052253e5a51fa9e31eae4d7ee2 (diff)
downloadsparse-2c80708a7c053671c344fc23e561621bdbcbae4d.tar.gz
do not linearize invalid expression
Code like: int *r; r = ({ __builtin_types_compatible_p(long, long); }); triggers the following diagnostics: warning: incorrect type in assignment (different base types) expected int *r got long warning: unknown expression (4 0) warning: unknown expression (4 0) The first warning is expected but the other two are bogus. The origin of the problem could be considered as being how type incompabilities are handled in assignment: If an incompatibility is found by compatible_assignment_types() - a warning is issued (not an error), - the source expression is casted to the destination type, - the returned value indicates a problem was detected. In the other uses of this function the returned value is simply ignored and normal processing continue. This seems logical since only a warning is issued and so (thanks to the cast) the resulting expression is at least type-coherent. However, in evaluate_assignment() the returned value is not ignored and the calling function directly returns. This leaves the resulting expression without a valid type, as if an error occured, unable to be correctly processed further. However, the real problem is that an expression without a valid type should never be linearized. So, in linearize_expression(), refuse to linearize an expression without a valid type. Note: if one is interested in doing a maximum of processing, including expansion and linearization, check_assignment_types() should be modified to distinguish between recoverable and non-recoverable type error (those for which the forced cast make sense and those for which it doesn't) and compatible_assignment_types() modified accordingly (maybe issuing a warning in the first case and an error otherwise). Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--linearize.c8
-rw-r--r--validation/eval-bad-assign1.c1
2 files changed, 6 insertions, 3 deletions
diff --git a/linearize.c b/linearize.c
index 415bf7e5..9ed66737 100644
--- a/linearize.c
+++ b/linearize.c
@@ -1764,7 +1764,7 @@ static pseudo_t linearize_cond_branch(struct entrypoint *ep, struct expression *
{
pseudo_t cond;
- if (!expr || !bb_reachable(ep->active))
+ if (!expr || !valid_type(expr->ctype) || !bb_reachable(ep->active))
return VOID;
switch (expr->type) {
@@ -1864,7 +1864,7 @@ static void linearize_argument(struct entrypoint *ep, struct symbol *arg, int nr
static pseudo_t linearize_expression(struct entrypoint *ep, struct expression *expr)
{
- if (!expr)
+ if (!expr || !valid_type(expr->ctype))
return VOID;
current_pos = expr->pos;
@@ -2417,6 +2417,10 @@ static pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stm
bb_true = alloc_basic_block(ep, stmt->pos);
bb_false = endif = alloc_basic_block(ep, stmt->pos);
+ // If the condition is invalid, the following
+ // statement(s) are not evaluated.
+ if (!cond || !valid_type(cond->ctype))
+ return VOID;
linearize_cond_branch(ep, cond, bb_true, bb_false);
set_activeblock(ep, bb_true);
diff --git a/validation/eval-bad-assign1.c b/validation/eval-bad-assign1.c
index bce4d3d3..57138c7a 100644
--- a/validation/eval-bad-assign1.c
+++ b/validation/eval-bad-assign1.c
@@ -5,7 +5,6 @@ static void kos(int *r, int a)
/*
* check-name: eval-bad-assign1
- * check-known-to-fail
*
* check-error-start
eval-bad-assign1.c:3:11: warning: incorrect type in assignment (different base types)