@@ -1719,24 +1719,32 @@ void c_typecheck_baset::typecheck_expr_trinary(if_exprt &expr)
17191719 operands[1 ].type ().id ()!=ID_pointer)
17201720 implicit_typecast (operands[1 ], operands[2 ].type ());
17211721
1722+ auto compile_time_null_pointer = [](const exprt &e, const namespacet &ns) {
1723+ if (!is_compile_time_constantt (ns)(e))
1724+ return false ;
1725+ auto s = simplify_expr (e, ns);
1726+ CHECK_RETURN (is_compile_time_constantt (ns)(s));
1727+ if (!s.is_constant ())
1728+ return false ;
1729+ return is_null_pointer (to_constant_expr (s));
1730+ };
1731+
17221732 if (operands[1 ].type ().id ()==ID_pointer &&
17231733 operands[2 ].type ().id ()==ID_pointer &&
17241734 operands[1 ].type ()!=operands[2 ].type ())
17251735 {
1726- exprt tmp1=simplify_expr (operands[1 ], *this );
1727- exprt tmp2=simplify_expr (operands[2 ], *this );
1728-
1729- // is one of them void * AND null? Convert that to the other.
1730- // (at least that's how GCC behaves)
1736+ // Is one of them void * AND null? Convert that to the other.
1737+ // (At least that's how GCC, Clang, and Visual Studio behave. Presence of
1738+ // symbols blocks them from simplifying the expression to NULL.)
17311739 if (
17321740 to_pointer_type (operands[1 ].type ()).base_type ().id () == ID_empty &&
1733- tmp1. is_constant () && is_null_pointer ( to_constant_expr (tmp1) ))
1741+ compile_time_null_pointer (operands[ 1 ], * this ))
17341742 {
17351743 implicit_typecast (operands[1 ], operands[2 ].type ());
17361744 }
17371745 else if (
17381746 to_pointer_type (operands[2 ].type ()).base_type ().id () == ID_empty &&
1739- tmp2. is_constant () && is_null_pointer ( to_constant_expr (tmp2) ))
1747+ compile_time_null_pointer (operands[ 2 ], * this ))
17401748 {
17411749 implicit_typecast (operands[2 ], operands[1 ].type ());
17421750 }
0 commit comments