+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
+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
/* 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:
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);
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> *);
+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
}
/* 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
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;
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))
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. */
+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.
}
/* 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;
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;
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;
}
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);
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,
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
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;
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)
{
@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
@hook TARGET_RESOLVE_OVERLOADED_BUILTIN
+@hook TARGET_CHECK_BUILTIN_CALL
+
@hook TARGET_FOLD_BUILTIN
@hook TARGET_GIMPLE_FOLD_BUILTIN
@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