@@ -3170,76 +3170,88 @@ exprt c_typecheck_baset::do_special_functions(
31703170 }
31713171 else if (
31723172 identifier == " __builtin_add_overflow" ||
3173+ identifier == " __builtin_add_overflow_p" )
3174+ {
3175+ return typecheck_builtin_overflow (expr, ID_plus);
3176+ }
3177+ else if (
31733178 identifier == " __builtin_sub_overflow" ||
3179+ identifier == " __builtin_sub_overflow_p" )
3180+ {
3181+ return typecheck_builtin_overflow (expr, ID_minus);
3182+ }
3183+ else if (
31743184 identifier == " __builtin_mul_overflow" ||
3175- identifier == " __builtin_add_overflow_p" ||
3176- identifier == " __builtin_sub_overflow_p" ||
31773185 identifier == " __builtin_mul_overflow_p" )
31783186 {
3179- // check function signature
3180- if (expr.arguments ().size () != 3 )
3181- {
3182- std::ostringstream error_message;
3183- error_message << expr.source_location ().as_string () << " : " << identifier
3184- << " takes exactly 3 arguments, but "
3185- << expr.arguments ().size () << " were provided" ;
3186- throw invalid_source_file_exceptiont{error_message.str ()};
3187- }
3187+ return typecheck_builtin_overflow (expr, ID_mult);
3188+ }
3189+ else
3190+ return nil_exprt ();
3191+ // NOLINTNEXTLINE(readability/fn_size)
3192+ }
31883193
3189- typecheck_function_call_arguments (expr);
3194+ exprt c_typecheck_baset::typecheck_builtin_overflow (
3195+ side_effect_expr_function_callt &expr,
3196+ const irep_idt &arith_op)
3197+ {
3198+ const irep_idt &identifier = to_symbol_expr (expr.function ()).get_identifier ();
31903199
3191- auto lhs = expr.arguments ()[0 ];
3192- auto rhs = expr.arguments ()[1 ];
3193- auto result = expr.arguments ()[2 ];
3194-
3195- const bool is__p_variant = has_suffix (id2string (identifier), " _p" );
3196-
3197- {
3198- auto const raise_wrong_argument_error =
3199- [this , identifier](
3200- const exprt &wrong_argument, std::size_t argument_number, bool _p) {
3201- std::ostringstream error_message;
3202- error_message << wrong_argument.source_location ().as_string () << " : "
3203- << identifier << " has signature " << identifier
3204- << " (integral, integral, integral" << (_p ? " " : " *" )
3205- << " ), "
3206- << " but argument " << argument_number << " ("
3207- << expr2c (wrong_argument, *this ) << " ) has type `"
3208- << type2c (wrong_argument.type (), *this ) << ' `' ;
3209- throw invalid_source_file_exceptiont{error_message.str ()};
3210- };
3211- for (int arg_index = 0 ; arg_index <= (!is__p_variant ? 1 : 2 ); ++arg_index)
3212- {
3213- auto const &argument = expr.arguments ()[arg_index];
3200+ // check function signature
3201+ if (expr.arguments ().size () != 3 )
3202+ {
3203+ std::ostringstream error_message;
3204+ error_message << expr.source_location ().as_string () << " : " << identifier
3205+ << " takes exactly 3 arguments, but "
3206+ << expr.arguments ().size () << " were provided" ;
3207+ throw invalid_source_file_exceptiont{error_message.str ()};
3208+ }
32143209
3215- if (!is_signed_or_unsigned_bitvector (argument.type ()))
3216- {
3217- raise_wrong_argument_error (argument, arg_index + 1 , is__p_variant);
3218- }
3219- }
3220- if (
3221- !is__p_variant &&
3222- (result.type ().id () != ID_pointer ||
3223- !is_signed_or_unsigned_bitvector (result.type ().subtype ())))
3210+ typecheck_function_call_arguments (expr);
3211+
3212+ auto lhs = expr.arguments ()[0 ];
3213+ auto rhs = expr.arguments ()[1 ];
3214+ auto result = expr.arguments ()[2 ];
3215+
3216+ const bool is__p_variant = has_suffix (id2string (identifier), " _p" );
3217+
3218+ {
3219+ auto const raise_wrong_argument_error =
3220+ [this , identifier](
3221+ const exprt &wrong_argument, std::size_t argument_number, bool _p) {
3222+ std::ostringstream error_message;
3223+ error_message << wrong_argument.source_location ().as_string () << " : "
3224+ << identifier << " has signature " << identifier
3225+ << " (integral, integral, integral" << (_p ? " " : " *" )
3226+ << " ), "
3227+ << " but argument " << argument_number << " ("
3228+ << expr2c (wrong_argument, *this ) << " ) has type `"
3229+ << type2c (wrong_argument.type (), *this ) << ' `' ;
3230+ throw invalid_source_file_exceptiont{error_message.str ()};
3231+ };
3232+ for (int arg_index = 0 ; arg_index <= (!is__p_variant ? 1 : 2 ); ++arg_index)
3233+ {
3234+ auto const &argument = expr.arguments ()[arg_index];
3235+
3236+ if (!is_signed_or_unsigned_bitvector (argument.type ()))
32243237 {
3225- raise_wrong_argument_error (result, 3 , is__p_variant);
3238+ raise_wrong_argument_error (argument, arg_index + 1 , is__p_variant);
32263239 }
32273240 }
3228-
3229- irep_idt kind =
3230- has_prefix (id2string (identifier), " __builtin_add_overflow" )
3231- ? ID_plus
3232- : has_prefix (id2string (identifier), " __builtin_sub_overflow" ) ? ID_minus
3233- : ID_mult;
3234-
3235- return side_effect_expr_overflowt{kind,
3236- std::move (lhs),
3237- std::move (rhs),
3238- std::move (result),
3239- expr.source_location ()};
3241+ if (
3242+ !is__p_variant &&
3243+ (result.type ().id () != ID_pointer ||
3244+ !is_signed_or_unsigned_bitvector (result.type ().subtype ())))
3245+ {
3246+ raise_wrong_argument_error (result, 3 , is__p_variant);
3247+ }
32403248 }
3241- else
3242- return nil_exprt ();
3249+
3250+ return side_effect_expr_overflowt{arith_op,
3251+ std::move (lhs),
3252+ std::move (rhs),
3253+ std::move (result),
3254+ expr.source_location ()};
32433255}
32443256
32453257// / Typecheck the parameters in a function call expression, and where
0 commit comments