diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fe6b333be6f..b6a19c4e2f7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2019-09-27 Richard Sandiford + + * 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 PR tree-optimization/91909 diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 93bdf3e0798..7b10957ad02 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,12 @@ +2019-09-27 Richard Sandiford + + * 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 * 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 3756219e5cf..7169813d0f2 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 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 a9f4d0c5c11..c1554f3c3af 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, - tree, int, tree *); + tree, tree, int, tree *); extern void check_function_format (const_tree, tree, int, tree *, vec *); 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, tree, - vec *, vec *); + vec *, vec *, + tree = NULL_TREE); extern tree resolve_overloaded_builtin (location_t, tree, vec *); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 96655493ac0..718e5b8b850 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,9 @@ +2019-09-27 Richard Sandiford + + * 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 PR c/91815 diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index d4e12eb93d1..cc13fdc84c8 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 arg_loc, tree function, vec *params, - vec *origtypes) + vec *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 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 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 1d30cef717e..3a3ef9ed250 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2019-09-27 Richard Sandiford + + * 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 PR c++/91877 - ICE with converting member of packed struct. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 45b984ecb11..5ccf3b89682 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 9c0f3949c68..8fc3fc1f78b 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 **, - 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 f427c4f4d3e..d549450a605 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 /*arg_loc*/, tree function, vec *params, - vec * /*origtypes*/) + vec * /*origtypes*/, tree orig_function) { vec *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 **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 **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 0250cf58e72..a86c210d4fe 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 @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 0b77dd8eb46..06dfcda35ab 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 01609136848..f9446fa05a2 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 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