@@ -81,6 +81,33 @@ class is_compile_time_constantt
81
81
{
82
82
return is_constant_address_of (to_address_of_expr (e).object ());
83
83
}
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
+ }
84
111
// we choose to accept the following expressions (over constant operands) as
85
112
// constant expressions
86
113
else if (
@@ -89,8 +116,7 @@ class is_compile_time_constantt
89
116
e.id () == ID_struct || e.id () == ID_union || e.id () == ID_empty_union ||
90
117
e.id () == ID_equal || e.id () == ID_notequal || e.id () == ID_lt ||
91
118
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 ||
94
120
e.id () == ID_bitor || e.id () == ID_bitxor || e.id () == ID_vector)
95
121
{
96
122
return std::all_of (
0 commit comments