@@ -1771,24 +1771,33 @@ void c_typecheck_baset::typecheck_expr_trinary(if_exprt &expr)
17711771 operands[1 ].type ().id ()!=ID_pointer)
17721772 implicit_typecast (operands[1 ], operands[2 ].type ());
17731773
1774+ auto compile_time_null_pointer = [](const exprt &e, const namespacet &ns)
1775+ {
1776+ if (!is_compile_time_constantt (ns)(e))
1777+ return false ;
1778+ auto s = simplify_expr (e, ns);
1779+ CHECK_RETURN (is_compile_time_constantt (ns)(s));
1780+ if (!s.is_constant ())
1781+ return false ;
1782+ return to_constant_expr (s).is_null_pointer ();
1783+ };
1784+
17741785 if (operands[1 ].type ().id ()==ID_pointer &&
17751786 operands[2 ].type ().id ()==ID_pointer &&
17761787 operands[1 ].type ()!=operands[2 ].type ())
17771788 {
1778- exprt tmp1=simplify_expr (operands[1 ], *this );
1779- exprt tmp2=simplify_expr (operands[2 ], *this );
1780-
1781- // is one of them void * AND null? Convert that to the other.
1782- // (at least that's how GCC behaves)
1789+ // Is one of them void * AND null? Convert that to the other.
1790+ // (At least that's how GCC, Clang, and Visual Studio behave. Presence of
1791+ // symbols blocks them from simplifying the expression to NULL.)
17831792 if (
17841793 to_pointer_type (operands[1 ].type ()).base_type ().id () == ID_empty &&
1785- tmp1. is_constant () && to_constant_expr (tmp1). is_null_pointer ( ))
1794+ compile_time_null_pointer (operands[ 1 ], * this ))
17861795 {
17871796 implicit_typecast (operands[1 ], operands[2 ].type ());
17881797 }
17891798 else if (
17901799 to_pointer_type (operands[2 ].type ()).base_type ().id () == ID_empty &&
1791- tmp2. is_constant () && to_constant_expr (tmp2). is_null_pointer ( ))
1800+ compile_time_null_pointer (operands[ 2 ], * this ))
17921801 {
17931802 implicit_typecast (operands[2 ], operands[1 ].type ());
17941803 }
0 commit comments