1919// / equal.
2020// / \param res: array of characters for the result
2121// / \param sval: a string constant
22+ // / \param guard: condition under which the axiom should apply, true by default
2223// / \return integer expression equal to zero
2324exprt string_constraint_generatort::add_axioms_for_constant (
2425 const array_string_exprt &res,
25- irep_idt sval)
26+ irep_idt sval,
27+ const exprt &guard)
2628{
2729 const typet &index_type = res.length ().type ();
2830 const typet &char_type = res.content ().type ().subtype ();
@@ -43,12 +45,12 @@ exprt string_constraint_generatort::add_axioms_for_constant(
4345 const exprt idx = from_integer (i, index_type);
4446 const exprt c = from_integer (str[i], char_type);
4547 const equal_exprt lemma (res[idx], c);
46- axioms.push_back (lemma);
48+ axioms.push_back (implies_exprt (guard, lemma) );
4749 }
4850
4951 const exprt s_length = from_integer (str.size (), index_type);
5052
51- axioms.push_back (res.axiom_for_has_length ( s_length));
53+ axioms.push_back (implies_exprt (guard, equal_exprt ( res.length (), s_length) ));
5254 return from_integer (0 , get_return_code_type ());
5355}
5456
@@ -65,6 +67,39 @@ exprt string_constraint_generatort::add_axioms_for_empty_string(
6567 return from_integer (0 , get_return_code_type ());
6668}
6769
70+ // / Convert an expression of type string_typet to a string_exprt
71+ // / \param res: string expression for the result
72+ // / \param arg: expression of type string typet
73+ // / \param guard: condition under which `res` should be equal to arg
74+ // / \return 0 if constraints were added, 1 if expression could not be handled
75+ // / and no constraint was added. Expression we can handle are of the
76+ // / form \f$ e := "<string constant>" | (expr)? e : e \f$
77+ exprt string_constraint_generatort::add_axioms_for_cprover_string (
78+ const array_string_exprt &res,
79+ const exprt &arg,
80+ const exprt &guard)
81+ {
82+ if (const auto if_expr = expr_try_dynamic_cast<if_exprt>(arg))
83+ {
84+ const and_exprt guard_true (guard, if_expr->cond ());
85+ const exprt return_code_true =
86+ add_axioms_for_cprover_string (res, if_expr->true_case (), guard_true);
87+
88+ const and_exprt guard_false (guard, not_exprt (if_expr->cond ()));
89+ const exprt return_code_false =
90+ add_axioms_for_cprover_string (res, if_expr->false_case (), guard_false);
91+
92+ return if_exprt (
93+ equal_exprt (return_code_true, from_integer (0 , get_return_code_type ())),
94+ return_code_false,
95+ return_code_true);
96+ }
97+ else if (const auto constant_expr = expr_try_dynamic_cast<constant_exprt>(arg))
98+ return add_axioms_for_constant (res, constant_expr->get_value (), guard);
99+ else
100+ return from_integer (1 , get_return_code_type ());
101+ }
102+
68103// / String corresponding to an internal cprover string
69104// /
70105// / Add axioms ensuring that the returned string expression is equal to the
@@ -79,7 +114,5 @@ exprt string_constraint_generatort::add_axioms_from_literal(
79114 const function_application_exprt::argumentst &args=f.arguments ();
80115 PRECONDITION (args.size () == 3 ); // Bad args to string literal?
81116 const array_string_exprt res = char_array_of_pointer (args[1 ], args[0 ]);
82- const exprt &arg = args[2 ];
83- irep_idt sval=to_constant_expr (arg).get_value ();
84- return add_axioms_for_constant (res, sval);
117+ return add_axioms_for_cprover_string (res, args[2 ], true_exprt ());
85118}
0 commit comments