@@ -1689,24 +1689,32 @@ void c_typecheck_baset::typecheck_expr_trinary(if_exprt &expr)
16891689 operands[1 ].type ().id ()!=ID_pointer)
16901690 implicit_typecast (operands[1 ], operands[2 ].type ());
16911691
1692+ auto compile_time_null_pointer = [](const exprt &e, const namespacet &ns) {
1693+ if (!is_compile_time_constantt (ns)(e))
1694+ return false ;
1695+ auto s = simplify_expr (e, ns);
1696+ CHECK_RETURN (is_compile_time_constantt (ns)(s));
1697+ if (!s.is_constant ())
1698+ return false ;
1699+ return is_null_pointer (to_constant_expr (s));
1700+ };
1701+
16921702 if (operands[1 ].type ().id ()==ID_pointer &&
16931703 operands[2 ].type ().id ()==ID_pointer &&
16941704 operands[1 ].type ()!=operands[2 ].type ())
16951705 {
1696- exprt tmp1=simplify_expr (operands[1 ], *this );
1697- exprt tmp2=simplify_expr (operands[2 ], *this );
1698-
1699- // is one of them void * AND null? Convert that to the other.
1700- // (at least that's how GCC behaves)
1706+ // Is one of them void * AND null? Convert that to the other.
1707+ // (At least that's how GCC, Clang, and Visual Studio behave. Presence of
1708+ // symbols blocks them from simplifying the expression to NULL.)
17011709 if (
17021710 to_pointer_type (operands[1 ].type ()).base_type ().id () == ID_empty &&
1703- tmp1. is_constant () && is_null_pointer ( to_constant_expr (tmp1) ))
1711+ compile_time_null_pointer (operands[ 1 ], * this ))
17041712 {
17051713 implicit_typecast (operands[1 ], operands[2 ].type ());
17061714 }
17071715 else if (
17081716 to_pointer_type (operands[2 ].type ()).base_type ().id () == ID_empty &&
1709- tmp2. is_constant () && is_null_pointer ( to_constant_expr (tmp2) ))
1717+ compile_time_null_pointer (operands[ 2 ], * this ))
17101718 {
17111719 implicit_typecast (operands[2 ], operands[1 ].type ());
17121720 }
0 commit comments