diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe6b333be6f054855ce5d419959b6af0ff7a561a..b6a19c4e2f7e07fc73858aeb1821eac7053cf9b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-09-27 Richard Sandiford <richard.sandiford@arm.com> + + * target.def (check_builtin_call): New target hook. + * doc/tm.texi.in (TARGET_CHECK_BUILTIN_CALL): New @hook. + * doc/tm.texi: Regenerate. + 2019-09-27 Richard Sandiford <richard.sandiford@arm.com> PR tree-optimization/91909 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 93bdf3e07988ec337cb4863143511d83cf0aa97f..7b10957ad02a0b7ee8af2e86be62965bbb944a6d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2019-09-27 Richard Sandiford <richard.sandiford@arm.com> + + * c-common.h (build_function_call_vec): Take the original + function decl as an optional final parameter. + (check_builtin_function_arguments): Take the original function decl. + * c-common.c (check_builtin_function_arguments): Likewise. + Handle all built-in functions, not just BUILT_IN_NORMAL ones. + Use targetm.check_builtin_call to check BUILT_IN_MD functions. + 2019-09-15 Jason Merrill <jason@redhat.com> * c-warn.c (warn_logical_operator): Strip location wrappers. Don't diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 3756219e5cf6921df320f8eeddf34ecb900b964d..7169813d0f26a1a3621d536748236b4ba8b5d904 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -5856,15 +5856,27 @@ builtin_function_validate_nargs (location_t loc, tree fndecl, int nargs, /* Verifies the NARGS arguments ARGS to the builtin function FNDECL. Returns false if there was an error, otherwise true. LOC is the location of the function; ARG_LOC is a vector of locations of the - arguments. */ + arguments. If FNDECL is the result of resolving an overloaded + target built-in, ORIG_FNDECL is the original function decl, + otherwise it is null. */ bool check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc, - tree fndecl, int nargs, tree *args) + tree fndecl, tree orig_fndecl, + int nargs, tree *args) { - if (!fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) + if (!fndecl_built_in_p (fndecl)) return true; + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD) + return (!targetm.check_builtin_call + || targetm.check_builtin_call (loc, arg_loc, fndecl, + orig_fndecl, nargs, args)); + + if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_FRONTEND) + return true; + + gcc_assert (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL); switch (DECL_FUNCTION_CODE (fndecl)) { case BUILT_IN_ALLOCA_WITH_ALIGN_AND_MAX: diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index a9f4d0c5c11e38b93db2a985da840c6532879176..c1554f3c3af2083a0bfff4323b14ccb097d1f9f2 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -818,7 +818,7 @@ extern void check_function_arguments_recurse (void (*) void *, tree, unsigned HOST_WIDE_INT); extern bool check_builtin_function_arguments (location_t, vec<location_t>, - tree, int, tree *); + tree, tree, int, tree *); extern void check_function_format (const_tree, tree, int, tree *, vec<location_t> *); extern bool attribute_fallthrough_p (tree); @@ -995,7 +995,8 @@ extern bool c_switch_covers_all_cases_p (splay_tree, tree); extern tree build_function_call (location_t, tree, tree); extern tree build_function_call_vec (location_t, vec<location_t>, tree, - vec<tree, va_gc> *, vec<tree, va_gc> *); + vec<tree, va_gc> *, vec<tree, va_gc> *, + tree = NULL_TREE); extern tree resolve_overloaded_builtin (location_t, tree, vec<tree, va_gc> *); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 96655493ac008fdf279eec22b34a124a44783cfa..718e5b8b8509ae5fcea958cfd71ebb0c1c0c78ac 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2019-09-27 Richard Sandiford <richard.sandiford@arm.com> + + * c-typeck.c (build_function_call_vec): Take the original function + decl as an optional final parameter. Pass all built-in calls to + check_builtin_function_arguments. + 2019-09-20 Eric Botcazou <ebotcazou@adacore.com> PR c/91815 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index d4e12eb93d1d2d774ed4f5964d5434e18d4109ae..cc13fdc84c879df59815c18cedfaef5685e413f4 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3003,6 +3003,8 @@ inform_declaration (tree decl) } /* Build a function call to function FUNCTION with parameters PARAMS. + If FUNCTION is the result of resolving an overloaded target built-in, + ORIG_FUNDECL is the original function decl, otherwise it is null. ORIGTYPES, if not NULL, is a vector of types; each element is either NULL or the original type of the corresponding element in PARAMS. The original type may differ from TREE_TYPE of the @@ -3013,7 +3015,7 @@ inform_declaration (tree decl) tree build_function_call_vec (location_t loc, vec<location_t> arg_loc, tree function, vec<tree, va_gc> *params, - vec<tree, va_gc> *origtypes) + vec<tree, va_gc> *origtypes, tree orig_fundecl) { tree fntype, fundecl = NULL_TREE; tree name = NULL_TREE, result; @@ -3033,6 +3035,8 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, if (flag_tm) tm_malloc_replacement (function); fundecl = function; + if (!orig_fundecl) + orig_fundecl = fundecl; /* Atomic functions have type checking/casting already done. They are often rewritten and don't match the original parameter list. */ if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9)) @@ -3110,9 +3114,10 @@ build_function_call_vec (location_t loc, vec<location_t> arg_loc, argarray = vec_safe_address (params); /* Check that arguments to builtin functions match the expectations. */ - if (fundecl && fndecl_built_in_p (fundecl, BUILT_IN_NORMAL) - && !check_builtin_function_arguments (loc, arg_loc, fundecl, nargs, - argarray)) + if (fundecl + && fndecl_built_in_p (fundecl) + && !check_builtin_function_arguments (loc, arg_loc, fundecl, + orig_fundecl, nargs, argarray)) return error_mark_node; /* Check that the arguments to the function are valid. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1d30cef717e2b7170c2f89bd54546a198e663a38..3a3ef9ed2502016bda5fbb7f23a4c5c3bb931f22 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2019-09-27 Richard Sandiford <richard.sandiford@arm.com> + + * cp-tree.h (build_cxx_call): Take the original function decl + as an optional final parameter. + (cp_build_function_call_vec): Likewise. + * call.c (build_cxx_call): Likewise. Pass all built-in calls to + check_builtin_function_arguments. + * typeck.c (build_function_call_vec): Take the original function + decl as an optional final parameter and pass it to + cp_build_function_call_vec. + (cp_build_function_call_vec): Take the original function + decl as an optional final parameter and pass it to build_cxx_call. + 2019-09-25 Marek Polacek <polacek@redhat.com> PR c++/91877 - ICE with converting member of packed struct. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 45b984ecb1185497361d5a4e424ab0fc7b4f8230..5ccf3b89682c114bcc2fd9773399a18752258556 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -9105,12 +9105,14 @@ maybe_warn_class_memaccess (location_t loc, tree fndecl, } /* Build and return a call to FN, using NARGS arguments in ARGARRAY. + If FN is the result of resolving an overloaded target built-in, + ORIG_FNDECL is the original function decl, otherwise it is null. This function performs no overload resolution, conversion, or other high-level operations. */ tree build_cxx_call (tree fn, int nargs, tree *argarray, - tsubst_flags_t complain) + tsubst_flags_t complain, tree orig_fndecl) { tree fndecl; @@ -9120,11 +9122,13 @@ build_cxx_call (tree fn, int nargs, tree *argarray, SET_EXPR_LOCATION (fn, loc); fndecl = get_callee_fndecl (fn); + if (!orig_fndecl) + orig_fndecl = fndecl; /* Check that arguments to builtin functions match the expectations. */ if (fndecl && !processing_template_decl - && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) + && fndecl_built_in_p (fndecl)) { int i; @@ -9134,7 +9138,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray, argarray[i] = maybe_constant_value (argarray[i]); if (!check_builtin_function_arguments (EXPR_LOCATION (fn), vNULL, fndecl, - nargs, argarray)) + orig_fndecl, nargs, argarray)) return error_mark_node; } diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9c0f3949c685fb989ae37451f01e2fcf169ee057..8fc3fc1f78bad743116bbce549c1e41f080f7791 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6257,7 +6257,8 @@ extern tree perform_direct_initialization_if_possible (tree, tree, bool, tsubst_flags_t); extern tree in_charge_arg_for_name (tree); extern tree build_cxx_call (tree, int, tree *, - tsubst_flags_t); + tsubst_flags_t, + tree = NULL_TREE); extern bool is_std_init_list (tree); extern bool is_list_ctor (tree); extern void validate_conversion_obstack (void); @@ -7391,7 +7392,8 @@ extern tree get_member_function_from_ptrfunc (tree *, tree, tsubst_flags_t); extern tree cp_build_function_call_nary (tree, tsubst_flags_t, ...) ATTRIBUTE_SENTINEL; extern tree cp_build_function_call_vec (tree, vec<tree, va_gc> **, - tsubst_flags_t); + tsubst_flags_t, + tree = NULL_TREE); extern tree build_x_binary_op (const op_location_t &, enum tree_code, tree, enum tree_code, tree, diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index f427c4f4d3e464b1270adce8cb0523cc8c8b41ac..d549450a605fa823a1c4054003025bc18447cc64 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -3773,11 +3773,11 @@ build_function_call (location_t /*loc*/, tree build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/, tree function, vec<tree, va_gc> *params, - vec<tree, va_gc> * /*origtypes*/) + vec<tree, va_gc> * /*origtypes*/, tree orig_function) { vec<tree, va_gc> *orig_params = params; tree ret = cp_build_function_call_vec (function, ¶ms, - tf_warning_or_error); + tf_warning_or_error, orig_function); /* cp_build_function_call_vec can reallocate PARAMS by adding default arguments. That should never happen here. Verify @@ -3818,13 +3818,15 @@ cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...) return ret; } -/* Build a function call using a vector of arguments. PARAMS may be - NULL if there are no parameters. This changes the contents of - PARAMS. */ +/* Build a function call using a vector of arguments. + If FUNCTION is the result of resolving an overloaded target built-in, + ORIG_FNDECL is the original function decl, otherwise it is null. + PARAMS may be NULL if there are no parameters. This changes the + contents of PARAMS. */ tree cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, - tsubst_flags_t complain) + tsubst_flags_t complain, tree orig_fndecl) { tree fntype, fndecl; int is_method; @@ -3949,7 +3951,7 @@ cp_build_function_call_vec (tree function, vec<tree, va_gc> **params, bool warned_p = check_function_arguments (input_location, fndecl, fntype, nargs, argarray, NULL); - ret = build_cxx_call (function, nargs, argarray, complain); + ret = build_cxx_call (function, nargs, argarray, complain, orig_fndecl); if (warned_p) { diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 0250cf58e72b4df8fec19cfb4399ed0e2594342b..a86c210d4fe390bd0356b6e50ba7c6c34a36239a 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11567,6 +11567,21 @@ another @code{CALL_EXPR}. @var{arglist} really has type @samp{VEC(tree,gc)*} @end deftypefn +@deftypefn {Target Hook} bool TARGET_CHECK_BUILTIN_CALL (location_t @var{loc}, vec<location_t> @var{arg_loc}, tree @var{fndecl}, tree @var{orig_fndecl}, unsigned int @var{nargs}, tree *@var{args}) +Perform semantic checking on a call to a machine-specific built-in +function after its arguments have been constrained to the function +signature. Return true if the call is valid, otherwise report an error +and return false. + +This hook is called after @code{TARGET_RESOLVE_OVERLOADED_BUILTIN}. +The call was originally to built-in function @var{orig_fndecl}, +but after the optional @code{TARGET_RESOLVE_OVERLOADED_BUILTIN} +step is now to built-in function @var{fndecl}. @var{loc} is the +location of the call and @var{args} is an array of function arguments, +of which there are @var{nargs}. @var{arg_loc} specifies the location +of each argument. +@end deftypefn + @deftypefn {Target Hook} tree TARGET_FOLD_BUILTIN (tree @var{fndecl}, int @var{n_args}, tree *@var{argp}, bool @var{ignore}) Fold a call to a machine specific built-in function that was set up by @samp{TARGET_INIT_BUILTINS}. @var{fndecl} is the declaration of the diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 0b77dd8eb46dc53fc585d7b3eac9805c6ed79951..06dfcda35abea7396c288a59c38ee4ef57c6fef6 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -7938,6 +7938,8 @@ to by @var{ce_info}. @hook TARGET_RESOLVE_OVERLOADED_BUILTIN +@hook TARGET_CHECK_BUILTIN_CALL + @hook TARGET_FOLD_BUILTIN @hook TARGET_GIMPLE_FOLD_BUILTIN diff --git a/gcc/target.def b/gcc/target.def index 01609136848fc157a47a93a0267c03524fe9383e..f9446fa05a22c79154c2ef36d3d8aea48a5efcc6 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -2397,6 +2397,24 @@ another @code{CALL_EXPR}.\n\ @var{arglist} really has type @samp{VEC(tree,gc)*}", tree, (unsigned int /*location_t*/ loc, tree fndecl, void *arglist), NULL) +DEFHOOK +(check_builtin_call, + "Perform semantic checking on a call to a machine-specific built-in\n\ +function after its arguments have been constrained to the function\n\ +signature. Return true if the call is valid, otherwise report an error\n\ +and return false.\n\ +\n\ +This hook is called after @code{TARGET_RESOLVE_OVERLOADED_BUILTIN}.\n\ +The call was originally to built-in function @var{orig_fndecl},\n\ +but after the optional @code{TARGET_RESOLVE_OVERLOADED_BUILTIN}\n\ +step is now to built-in function @var{fndecl}. @var{loc} is the\n\ +location of the call and @var{args} is an array of function arguments,\n\ +of which there are @var{nargs}. @var{arg_loc} specifies the location\n\ +of each argument.", + bool, (location_t loc, vec<location_t> arg_loc, tree fndecl, + tree orig_fndecl, unsigned int nargs, tree *args), + NULL) + /* Fold a target-specific builtin to a tree valid for both GIMPLE and GENERIC. */ DEFHOOK