+ llassert (exprNode_isDefined(e));
+
+ if (! (exprNode_isDefined(e)))
+ return FALSE;
+
+ if (e->kind != XPR_SIZEOF)
+ return FALSE;
+
+ t = exprData_getSingle (e->edata);
+ s1 = exprNode_getSref (t);
+
+ s2 = constraintTerm_getsRef(constraintExprData_termGetTerm(buf1->data) );
+
+ /*drl this may be the wronge thing to test for but this
+ seems to work correctly*/
+ if (sRef_similarRelaxed(s1, s2) || sRef_sameName (s1, s2) )
+ {
+ /* origly checked that ctype_isFixedArray(sRef_getType(s2)) but
+ removed that test */
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/* look for the special case of
+ maxSet(buf) >= sizeof(buf) - 1
+*/
+
+/*drl eventually it would be good to check that
+ buf is of type char.*/
+
+static bool sizeOfMaxSet( /*@observer@*/ /*@temp@*/ constraint c)
+{
+ constraintExpr l, r, buf1, buf2, con;
+
+ DPRINTF(( message("sizeOfMaxSet: checking %s ", constraint_unparse(c) )
+ ));
+
+ llassertfatal (constraint_isDefined(c) );
+
+ l = c->lexpr;
+ r = c->expr;
+
+ if (!((c->ar == EQ) || (c->ar == GTE) || (c->ar == LTE) ) )
+ return FALSE;
+
+ llassert (constraintExpr_isDefined(l) );
+ llassert (constraintExpr_isDefined(r) );
+
+ /*check if the constraintExpr is MaxSet(buf) */
+ if (l->kind == unaryExpr)
+ {
+ if (constraintExprData_unaryExprGetOp(l->data) == MAXSET)
+ {
+ buf1 = constraintExprData_unaryExprGetExpr(l->data);
+ }
+ else
+ return FALSE;
+ }
+ else
+ return FALSE;
+
+
+ if (r->kind != binaryexpr)
+ return FALSE;
+
+ buf2 = constraintExprData_binaryExprGetExpr1(r->data);
+ con = constraintExprData_binaryExprGetExpr2(r->data);
+
+ if (constraintExprData_binaryExprGetOp(r->data) == BINARYOP_MINUS)
+ {
+ if (constraintExpr_canGetValue(con) )
+ {
+ long i;
+
+ i = constraintExpr_getValue(con);
+ if (i != 1)
+ {
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+ }
+
+ if (constraintExprData_binaryExprGetOp(r->data) == BINARYOP_PLUS)
+ {
+ if (constraintExpr_canGetValue(con) )
+ {
+ long i;
+
+ i = constraintExpr_getValue(con);
+ if (i != -1)
+ {
+ return FALSE;
+ }
+ }
+ else
+ return FALSE;
+ }
+
+ if (sizeofBufComp(buf1, buf2))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+/*@noaccess constraintExpr@*/
+
+/* We look for constraint which are tautologies */
+
+bool constraint_isAlwaysTrue (/*@observer@*/ /*@temp@*/ constraint c)
+{
+ constraintExpr l, r;
+ bool rHasConstant;
+ int rConstant;
+
+
+ llassert (constraint_isDefined(c) );
+
+ l = c->lexpr;
+ r = c->expr;
+
+ DPRINTF(( message("constraint_IsAlwaysTrue:examining %s", constraint_unparse(c) ) ));
+
+ if (sizeOfMaxSet(c) )
+ return TRUE;
+
+ if (constraintExpr_canGetValue(l) && constraintExpr_canGetValue(r) )
+ {
+ int cmp;
+ cmp = constraintExpr_compare (l, r);
+ switch (c->ar)
+ {
+ case EQ:
+ return (cmp == 0);
+ case GT:
+ return (cmp > 0);
+ case GTE:
+ return (cmp >= 0);
+ case LTE:
+ return (cmp <= 0);
+ case LT:
+ return (cmp < 0);
+
+ default:
+ BADEXIT;
+ /*@notreached@*/
+ break;
+ }
+ }
+
+ if (constraintExpr_similar (l,r))
+ {
+ switch (c->ar)
+ {
+ case EQ:
+ case GTE:
+ case LTE:
+ return TRUE;
+
+ case GT:
+ case LT:
+ break;
+ default:
+ BADEXIT;
+ /*@notreached@*/
+ break;
+ }
+ }
+
+ l = constraintExpr_copy (c->lexpr);
+ r = constraintExpr_copy (c->expr);
+
+ r = constraintExpr_propagateConstants (r, &rHasConstant, &rConstant);
+
+ if (constraintExpr_similar (l,r) && (rHasConstant ) )
+ {
+ DPRINTF(( message("constraint_IsAlwaysTrue: after removing constants %s and %s are similar", constraintExpr_unparse(l), constraintExpr_unparse(r) ) ));
+ DPRINTF(( message("constraint_IsAlwaysTrue: rconstant is %d", rConstant ) ));
+
+ constraintExpr_free(l);
+ constraintExpr_free(r);
+
+ switch (c->ar)
+ {
+ case EQ:
+ return (rConstant == 0);
+ case LT:
+ return (rConstant > 0);
+ case LTE:
+ return (rConstant >= 0);
+ case GTE:
+ return (rConstant <= 0);
+ case GT:
+ return (rConstant < 0);
+
+ default:
+ BADEXIT;
+ /*@notreached@*/
+ break;
+ }
+ }
+ else
+ {
+ constraintExpr_free(l);
+ constraintExpr_free(r);
+ DPRINTF(( message("Constraint %s is not always true", constraint_unparse(c) ) ));
+ return FALSE;
+ }
+
+ BADEXIT;
+}
+
+static bool rangeCheck (arithType ar1, /*@observer@*/ constraintExpr expr1, arithType ar2, /*@observer@*/ constraintExpr expr2)
+
+{
+ DPRINTF (("Doing range check %s and %s",
+ constraintExpr_unparse (expr1), constraintExpr_unparse (expr2)));
+
+ if (!arithType_canResolve (ar1, ar2))
+ return FALSE;
+
+ switch (ar1)
+ {
+ case GTE:
+ if (constraintExpr_similar (expr1, expr2) )
+ return TRUE;
+ /*@fallthrough@*/
+ case GT:
+ if (! (constraintExpr_canGetValue (expr1) &&
+ constraintExpr_canGetValue (expr2) ) )
+ {
+ constraintExpr e1, e2;
+ bool p1, p2;
+ int const1, const2;
+
+ e1 = constraintExpr_copy(expr1);
+ e2 = constraintExpr_copy(expr2);
+
+ e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
+ e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
+
+ if (p1 || p2)
+ {
+ if (!p1)
+ const1 = 0;
+
+ if (!p2)
+ const2 = 0;
+
+ if (const1 <= const2)
+ if (constraintExpr_similar (e1, e2) )
+ {
+ constraintExpr_free(e1);
+ constraintExpr_free(e2);
+ return TRUE;
+ }
+ }
+ DPRINTF(("Can't Get value"));
+
+ constraintExpr_free(e1);
+ constraintExpr_free(e2);
+ return FALSE;
+ }
+
+ if (constraintExpr_compare (expr2, expr1) >= 0)
+ return TRUE;
+
+ return FALSE;
+ case EQ:
+ if (constraintExpr_similar (expr1, expr2) )
+ return TRUE;
+
+ return FALSE;
+ case LTE:
+ if (constraintExpr_similar (expr1, expr2) )
+ return TRUE;
+ /*@fallthrough@*/
+ case LT:
+ if (! (constraintExpr_canGetValue (expr1) &&
+ constraintExpr_canGetValue (expr2) ) )
+ {
+ constraintExpr e1, e2;
+ bool p1, p2;
+ int const1, const2;
+
+ e1 = constraintExpr_copy(expr1);
+ e2 = constraintExpr_copy(expr2);
+
+ e1 = constraintExpr_propagateConstants (e1, &p1, &const1);
+
+ e2 = constraintExpr_propagateConstants (e2, &p2, &const2);
+
+ if (p1 || p2)
+ {
+ if (!p1)
+ const1 = 0;
+
+ if (!p2)
+ const2 = 0;
+
+ if (const1 >= const2)
+ if (constraintExpr_similar (e1, e2) )
+ {
+ constraintExpr_free(e1);
+ constraintExpr_free(e2);
+ return TRUE;
+ }
+ }
+ constraintExpr_free(e1);
+ constraintExpr_free(e2);
+
+ DPRINTF(("Can't Get value"));
+ return FALSE;
+ }
+
+ if (constraintExpr_compare (expr2, expr1) <= 0)
+ return TRUE;
+
+ return FALSE;
+
+ default:
+ llcontbug((message("Unhandled case in switch: %q", arithType_print(ar1) ) ) );
+ }
+ BADEXIT;
+}
+
+static constraint constraint_searchandreplace (/*@returned@*/ constraint c, constraintExpr old, constraintExpr newExpr)
+{
+ llassertfatal (constraint_isDefined(c));
+
+ DPRINTF (("Starting replace lexpr [%p]: %s < %s ==> %s > in %s", c,
+ constraintExpr_unparse (c->lexpr),
+ constraintExpr_unparse (old), constraintExpr_unparse (newExpr),
+ constraint_unparse (c)));
+ c->lexpr = constraintExpr_searchandreplace (c->lexpr, old, newExpr);
+ DPRINTF (("Finished replace lexpr [%p]: %s", c, constraintExpr_unparse (c->lexpr)));
+ c->expr = constraintExpr_searchandreplace (c->expr, old, newExpr);
+ return c;
+}
+
+bool constraint_search (constraint c, constraintExpr old) /*@*/
+{