Skip to content

Commit 60d24b7

Browse files
committed
is_compile_time_constantt: honour short-circuit semantics
The C standard stipulates that short-circuit semantics should be honoured when considering whether an expression is a "constant expression."
1 parent 8430887 commit 60d24b7

File tree

1 file changed

+28
-2
lines changed

1 file changed

+28
-2
lines changed

Diff for: src/ansi-c/c_typecheck_expr.cpp

+28-2
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)