aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLinus Torvalds <torvalds@penguin.transmeta.com>2003-04-04 16:28:05 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-07 21:00:12 -0700
commit712f630a63f795a09cc0dba8096c13d208ca7039 (patch)
tree678d71991dbf3bdff03a646b1bd271466c2c49a0
parentbc5f5ac6db207545064aabf73ba3cde9622742f2 (diff)
downloadsparse-dev-712f630a63f795a09cc0dba8096c13d208ca7039.tar.gz
Evaluate conditional expressions with the gcc extension
(ie 'a ? : b' is equivalent to 'a ? a : b' modulo side effects). Simplify conditional expressions.
-rw-r--r--evaluate.c51
1 files changed, 30 insertions, 21 deletions
diff --git a/evaluate.c b/evaluate.c
index e6793dc9..153ab34d 100644
--- a/evaluate.c
+++ b/evaluate.c
@@ -589,29 +589,36 @@ static struct symbol *compatible_ptr_type(struct expression *left, struct expres
static struct symbol * evaluate_conditional(struct expression *expr)
{
- struct symbol *ctype;
- struct symbol *ltype = expr->cond_true->ctype;
- struct symbol *rtype = expr->cond_false->ctype;
+ struct expression *cond, *true, *false;
+ struct symbol *ctype, *ltype, *rtype;
- if (same_type(ltype, rtype)) {
- expr->ctype = ltype;
- return ltype;
- }
+ cond = expr->conditional;
+ true = expr->cond_true ? : cond;
+ false = expr->cond_false;
- ctype = compatible_integer_binop(expr, &expr->cond_true, &expr->cond_false);
- if (ctype) {
- expr->ctype = ctype;
- return ctype;
- }
+ ltype = true->ctype;
+ rtype = false->ctype;
- ctype = compatible_ptr_type(expr->cond_true, expr->cond_false);
- if (ctype) {
- expr->ctype = ctype;
- return ctype;
+ ctype = ltype;
+ if (!same_type(ltype, rtype)) {
+ ctype = compatible_integer_binop(expr, &true, &expr->cond_false);
+ if (!ctype) {
+ ctype = compatible_ptr_type(true, expr->cond_false);
+ if (!ctype) {
+ warn(expr->pos, "incompatible types in conditional expression");
+ return NULL;
+ }
+ }
}
- warn(expr->pos, "incompatible types in conditional expression");
- return NULL;
+ /* Simplify conditional expression.. */
+ if (cond->type == EXPR_VALUE) {
+ if (!cond->value)
+ true = false;
+ *expr = *true;
+ }
+ expr->ctype = ctype;
+ return ctype;
}
static int compatible_assignment_types(struct expression *expr, struct symbol *target,
@@ -1176,9 +1183,11 @@ struct symbol *evaluate_expression(struct expression *expr)
warn(expr->pos, "bitfield generated by parser");
return NULL;
case EXPR_CONDITIONAL:
- if (!evaluate_expression(expr->conditional) ||
- !evaluate_expression(expr->cond_true) ||
- !evaluate_expression(expr->cond_false))
+ if (!evaluate_expression(expr->conditional))
+ return NULL;
+ if (!evaluate_expression(expr->cond_false))
+ return NULL;
+ if (expr->cond_true && !evaluate_expression(expr->cond_true))
return NULL;
return evaluate_conditional(expr);
case EXPR_STATEMENT: