@@ -81,6 +81,33 @@ class is_compile_time_constantt
8181 {
8282 return is_constant_address_of (to_address_of_expr (e).object ());
8383 }
84+ // we need to adhere to short-circuit semantics for the following
85+ else if (e.id () == ID_if)
86+ {
87+ const if_exprt &if_expr = to_if_expr (e);
88+ if (!is_constant (if_expr.cond ()))
89+ return false ;
90+ exprt const_cond = simplify_expr (if_expr.cond (), ns);
91+ CHECK_RETURN (const_cond.is_constant ());
92+ if (const_cond.is_true ())
93+ return is_constant (if_expr.true_case ());
94+ else
95+ return is_constant (if_expr.false_case ());
96+ }
97+ else if (e.id () == ID_and || e.id () == ID_or)
98+ {
99+ for (const auto &op : e.operands ())
100+ {
101+ if (!is_constant (op))
102+ return false ;
103+ exprt const_cond = simplify_expr (op, ns);
104+ CHECK_RETURN (const_cond.is_constant ());
105+ // stop when we hit false (for an and) or true (for an or)
106+ if (const_cond == make_boolean_expr (e.id () == ID_or))
107+ break ;
108+ }
109+ return true ;
110+ }
84111 // we choose to accept the following expressions (over constant operands) as
85112 // constant expressions
86113 else if (
@@ -89,8 +116,7 @@ class is_compile_time_constantt
89116 e.id () == ID_struct || e.id () == ID_union || e.id () == ID_empty_union ||
90117 e.id () == ID_equal || e.id () == ID_notequal || e.id () == ID_lt ||
91118 e.id () == ID_le || e.id () == ID_gt || e.id () == ID_ge ||
92- e.id () == ID_if || e.id () == ID_not || e.id () == ID_and ||
93- e.id () == ID_or || e.id () == ID_bitnot || e.id () == ID_bitand ||
119+ e.id () == ID_not || e.id () == ID_bitnot || e.id () == ID_bitand ||
94120 e.id () == ID_bitor || e.id () == ID_bitxor || e.id () == ID_vector)
95121 {
96122 return std::all_of (
0 commit comments