@@ -1689,24 +1689,31 @@ 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+ if (!s.is_constant ())
1697+ return false ;
1698+ return is_null_pointer (to_constant_expr (s));
1699+ };
1700+
16921701 if (operands[1 ].type ().id ()==ID_pointer &&
16931702 operands[2 ].type ().id ()==ID_pointer &&
16941703 operands[1 ].type ()!=operands[2 ].type ())
16951704 {
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)
1705+ // Is one of them void * AND null? Convert that to the other.
1706+ // (At least that's how GCC, Clang, and Visual Studio behave. Presence of
1707+ // symbols blocks them from simplifying the expression to NULL.)
17011708 if (
17021709 to_pointer_type (operands[1 ].type ()).base_type ().id () == ID_empty &&
1703- tmp1. is_constant () && is_null_pointer ( to_constant_expr (tmp1) ))
1710+ compile_time_null_pointer (operands[ 1 ], * this ))
17041711 {
17051712 implicit_typecast (operands[1 ], operands[2 ].type ());
17061713 }
17071714 else if (
17081715 to_pointer_type (operands[2 ].type ()).base_type ().id () == ID_empty &&
1709- tmp2. is_constant () && is_null_pointer ( to_constant_expr (tmp2) ))
1716+ compile_time_null_pointer (operands[ 2 ], * this ))
17101717 {
17111718 implicit_typecast (operands[2 ], operands[1 ].type ());
17121719 }
0 commit comments