@@ -3170,76 +3170,88 @@ exprt c_typecheck_baset::do_special_functions(
3170
3170
}
3171
3171
else if (
3172
3172
identifier == " __builtin_add_overflow" ||
3173
+ identifier == " __builtin_add_overflow_p" )
3174
+ {
3175
+ return typecheck_builtin_overflow (expr, ID_plus);
3176
+ }
3177
+ else if (
3173
3178
identifier == " __builtin_sub_overflow" ||
3179
+ identifier == " __builtin_sub_overflow_p" )
3180
+ {
3181
+ return typecheck_builtin_overflow (expr, ID_minus);
3182
+ }
3183
+ else if (
3174
3184
identifier == " __builtin_mul_overflow" ||
3175
- identifier == " __builtin_add_overflow_p" ||
3176
- identifier == " __builtin_sub_overflow_p" ||
3177
3185
identifier == " __builtin_mul_overflow_p" )
3178
3186
{
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
+ }
3188
3193
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 ();
3190
3199
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
+ }
3214
3209
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 ()))
3224
3237
{
3225
- raise_wrong_argument_error (result, 3 , is__p_variant);
3238
+ raise_wrong_argument_error (argument, arg_index + 1 , is__p_variant);
3226
3239
}
3227
3240
}
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
+ }
3240
3248
}
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 ()};
3243
3255
}
3244
3256
3245
3257
// / Typecheck the parameters in a function call expression, and where
0 commit comments