diff options
author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-03-05 00:23:13 +0100 |
---|---|---|
committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2019-09-30 02:09:45 +0200 |
commit | 2c80708a7c053671c344fc23e561621bdbcbae4d (patch) | |
tree | 7cbf46b4a72a7153ced66036081af043c7110922 | |
parent | c1d5521fcd0220052253e5a51fa9e31eae4d7ee2 (diff) | |
download | sparse-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.c | 8 | ||||
-rw-r--r-- | validation/eval-bad-assign1.c | 1 |
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) |