Commit cb1180d5 by Richard Sandiford Committed by Richard Sandiford

Protect some checks of DECL_FUNCTION_CODE

This patch protects various uses of DECL_FUNCTION_CODE that didn't
obviously check for BUILT_IN_NORMAL first (either directly or in callers).
They could therefore trigger for functions that either aren't built-ins
or are a different kind of built-in.

Also, the patch removes a redundant GIMPLE_CALL check from
optimize_stdarg_builtin, since it gave the impression that the stmt
was less well checked than it actually is.

2019-08-13  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	PR middle-end/91421
	* attribs.c (decl_attributes): Check the DECL_BUILT_IN_CLASS
	before the DECL_FUNCTION_CODE.
	* calls.c (maybe_warn_alloc_args_overflow): Use fndecl_built_in_p
	to check for a BUILT_IN_ALLOCA call.
	* ipa-cp.c (ipa_get_indirect_edge_target_1): Likewise for
	BUILT_IN_UNREACHABLE.  Don't check for a FUNCTION_TYPE.
	* ipa-devirt.c (possible_polymorphic_call_target_p): Likewise.
	* ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.
	* gimple-ssa-isolate-paths.c (is_addr_local): Check specifically
	for BUILT_IN_NORMAL functions.
	* trans-mem.c (expand_block_edges): Use gimple_call_builtin_p to
	test for BUILT_IN_TM_ABORT.
	* tree-ssa-ccp.c (optimize_stack_restore): Use fndecl_built_in_p
	to check for a BUILT_IN_STACK_RESTORE call.
	(optimize_stdarg_builtin): Remove redundant check for GIMPLE_CALL.
	* tree-ssa-threadedge.c
	(record_temporary_equivalences_from_stmts_at_dest): Check for a
	BUILT_IN_NORMAL decl before checking its DECL_FUNCTION_CODE.
	* tree-vect-patterns.c (vect_recog_pow_pattern): Use a positive
	test for a BUILT_IN_NORMAL call instead of a negative test for
	an internal function call.

gcc/c/
	PR middle-end/91421
	* c-decl.c (header_for_builtin_fn): Take a FUNCTION_DECL instead
	of a built_in_function.
	(diagnose_mismatched_decls, implicitly_declare): Update accordingly.

From-SVN: r274403
parent 0b1fe8cf
2019-08-13 Richard Sandiford <richard.sandiford@arm.com> 2019-08-13 Richard Sandiford <richard.sandiford@arm.com>
PR middle-end/91421
* attribs.c (decl_attributes): Check the DECL_BUILT_IN_CLASS
before the DECL_FUNCTION_CODE.
* calls.c (maybe_warn_alloc_args_overflow): Use fndecl_built_in_p
to check for a BUILT_IN_ALLOCA call.
* ipa-cp.c (ipa_get_indirect_edge_target_1): Likewise for
BUILT_IN_UNREACHABLE. Don't check for a FUNCTION_TYPE.
* ipa-devirt.c (possible_polymorphic_call_target_p): Likewise.
* ipa-prop.c (try_make_edge_direct_virtual_call): Likewise.
* gimple-ssa-isolate-paths.c (is_addr_local): Check specifically
for BUILT_IN_NORMAL functions.
* trans-mem.c (expand_block_edges): Use gimple_call_builtin_p to
test for BUILT_IN_TM_ABORT.
* tree-ssa-ccp.c (optimize_stack_restore): Use fndecl_built_in_p
to check for a BUILT_IN_STACK_RESTORE call.
(optimize_stdarg_builtin): Remove redundant check for GIMPLE_CALL.
* tree-ssa-threadedge.c
(record_temporary_equivalences_from_stmts_at_dest): Check for a
BUILT_IN_NORMAL decl before checking its DECL_FUNCTION_CODE.
* tree-vect-patterns.c (vect_recog_pow_pattern): Use a positive
test for a BUILT_IN_NORMAL call instead of a negative test for
an internal function call.
2019-08-13 Richard Sandiford <richard.sandiford@arm.com>
* tree.h (build_vector_a_then_b): Declare. * tree.h (build_vector_a_then_b): Declare.
* tree.c (build_vector_a_then_b): New function. * tree.c (build_vector_a_then_b): New function.
* fold-const-call.c (fold_while_ult): Likewise. * fold-const-call.c (fold_while_ult): Likewise.
......
...@@ -691,6 +691,7 @@ decl_attributes (tree *node, tree attributes, int flags, ...@@ -691,6 +691,7 @@ decl_attributes (tree *node, tree attributes, int flags,
if (!built_in if (!built_in
|| !DECL_P (*anode) || !DECL_P (*anode)
|| DECL_BUILT_IN_CLASS (*anode) != BUILT_IN_NORMAL
|| (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE || (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE
&& (DECL_FUNCTION_CODE (*anode) && (DECL_FUNCTION_CODE (*anode)
!= BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE))) != BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE)))
......
2019-08-13 Richard Sandiford <richard.sandiford@arm.com>
PR middle-end/91421
* c-decl.c (header_for_builtin_fn): Take a FUNCTION_DECL instead
of a built_in_function.
(diagnose_mismatched_decls, implicitly_declare): Update accordingly.
2019-08-10 Jakub Jelinek <jakub@redhat.com> 2019-08-10 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (c_parser_omp_clause_name): Parse device_type. * c-parser.c (c_parser_omp_clause_name): Parse device_type.
......
...@@ -605,7 +605,7 @@ static tree grokparms (struct c_arg_info *, bool); ...@@ -605,7 +605,7 @@ static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree); static void layout_array_type (tree);
static void warn_defaults_to (location_t, int, const char *, ...) static void warn_defaults_to (location_t, int, const char *, ...)
ATTRIBUTE_GCC_DIAG(3,4); ATTRIBUTE_GCC_DIAG(3,4);
static const char *header_for_builtin_fn (enum built_in_function); static const char *header_for_builtin_fn (tree);
/* T is a statement. Add it to the statement-tree. This is the /* T is a statement. Add it to the statement-tree. This is the
C/ObjC version--C++ has a slightly different version of this C/ObjC version--C++ has a slightly different version of this
...@@ -1953,7 +1953,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ...@@ -1953,7 +1953,8 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
if (!comptypes (oldtype, newtype)) if (!comptypes (oldtype, newtype))
{ {
if (TREE_CODE (olddecl) == FUNCTION_DECL if (TREE_CODE (olddecl) == FUNCTION_DECL
&& fndecl_built_in_p (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl)) && fndecl_built_in_p (olddecl, BUILT_IN_NORMAL)
&& !C_DECL_DECLARED_BUILTIN (olddecl))
{ {
/* Accept "harmless" mismatches in function types such /* Accept "harmless" mismatches in function types such
as missing qualifiers or pointer vs same size integer as missing qualifiers or pointer vs same size integer
...@@ -1975,8 +1976,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ...@@ -1975,8 +1976,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* If types don't match for a built-in, throw away the /* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it built-in. No point in calling locate_old_decl here, it
won't print anything. */ won't print anything. */
const char *header const char *header = header_for_builtin_fn (olddecl);
= header_for_builtin_fn (DECL_FUNCTION_CODE (olddecl));
location_t loc = DECL_SOURCE_LOCATION (newdecl); location_t loc = DECL_SOURCE_LOCATION (newdecl);
if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch, if (warning_at (loc, OPT_Wbuiltin_declaration_mismatch,
"conflicting types for built-in function %q+D; " "conflicting types for built-in function %q+D; "
...@@ -3339,13 +3339,17 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl) ...@@ -3339,13 +3339,17 @@ implicit_decl_warning (location_t loc, tree id, tree olddecl)
hint.suppress (); hint.suppress ();
} }
/* This function represents mapping of a function code FCODE /* Return the name of the header file that declares built-in function
to its respective header. */ FNDECL, or null if either we don't know or don't expect to see an
explicit declaration. */
static const char * static const char *
header_for_builtin_fn (enum built_in_function fcode) header_for_builtin_fn (tree fndecl)
{ {
switch (fcode) if (DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
return NULL;
switch (DECL_FUNCTION_CODE (fndecl))
{ {
CASE_FLT_FN (BUILT_IN_ACOS): CASE_FLT_FN (BUILT_IN_ACOS):
CASE_FLT_FN (BUILT_IN_ACOSH): CASE_FLT_FN (BUILT_IN_ACOSH):
...@@ -3595,8 +3599,7 @@ implicitly_declare (location_t loc, tree functionid) ...@@ -3595,8 +3599,7 @@ implicitly_declare (location_t loc, tree functionid)
"declaration of built-in " "declaration of built-in "
"function %qD", decl); "function %qD", decl);
/* See if we can hint which header to include. */ /* See if we can hint which header to include. */
const char *header const char *header = header_for_builtin_fn (decl);
= header_for_builtin_fn (DECL_FUNCTION_CODE (decl));
if (header != NULL && warned) if (header != NULL && warned)
{ {
rich_location richloc (line_table, loc); rich_location richloc (line_table, loc);
......
...@@ -1350,7 +1350,6 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) ...@@ -1350,7 +1350,6 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
location_t loc = EXPR_LOCATION (exp); location_t loc = EXPR_LOCATION (exp);
tree fntype = fn ? TREE_TYPE (fn) : TREE_TYPE (TREE_TYPE (exp)); tree fntype = fn ? TREE_TYPE (fn) : TREE_TYPE (TREE_TYPE (exp));
built_in_function fncode = fn ? DECL_FUNCTION_CODE (fn) : BUILT_IN_NONE;
bool warned = false; bool warned = false;
/* Validate each argument individually. */ /* Validate each argument individually. */
...@@ -1376,11 +1375,10 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2]) ...@@ -1376,11 +1375,10 @@ maybe_warn_alloc_args_overflow (tree fn, tree exp, tree args[2], int idx[2])
friends. friends.
Also avoid issuing the warning for calls to function named Also avoid issuing the warning for calls to function named
"alloca". */ "alloca". */
if ((fncode == BUILT_IN_ALLOCA if (fn && fndecl_built_in_p (fn, BUILT_IN_ALLOCA)
&& IDENTIFIER_LENGTH (DECL_NAME (fn)) != 6) ? IDENTIFIER_LENGTH (DECL_NAME (fn)) != 6
|| (fncode != BUILT_IN_ALLOCA : !lookup_attribute ("returns_nonnull",
&& !lookup_attribute ("returns_nonnull", TYPE_ATTRIBUTES (fntype)))
TYPE_ATTRIBUTES (fntype))))
warned = warning_at (loc, OPT_Walloc_zero, warned = warning_at (loc, OPT_Walloc_zero,
"%Kargument %i value is zero", "%Kargument %i value is zero",
exp, idx[i] + 1); exp, idx[i] + 1);
......
...@@ -502,7 +502,7 @@ is_addr_local (gimple *return_stmt, tree exp, locmap_t *plocmap, ...@@ -502,7 +502,7 @@ is_addr_local (gimple *return_stmt, tree exp, locmap_t *plocmap,
} }
if (code == GIMPLE_CALL if (code == GIMPLE_CALL
&& gimple_call_builtin_p (def_stmt)) && gimple_call_builtin_p (def_stmt, BUILT_IN_NORMAL))
{ {
/* Handle alloca and friends that return pointers to automatic /* Handle alloca and friends that return pointers to automatic
storage. */ storage. */
......
...@@ -2436,8 +2436,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, ...@@ -2436,8 +2436,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie,
if (can_refer) if (can_refer)
{ {
if (!target if (!target
|| (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE || fndecl_built_in_p (target, BUILT_IN_UNREACHABLE)
&& DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE)
|| !possible_polymorphic_call_target_p || !possible_polymorphic_call_target_p
(ie, cgraph_node::get (target))) (ie, cgraph_node::get (target)))
{ {
......
...@@ -3426,12 +3426,10 @@ possible_polymorphic_call_target_p (tree otr_type, ...@@ -3426,12 +3426,10 @@ possible_polymorphic_call_target_p (tree otr_type,
{ {
vec <cgraph_node *> targets; vec <cgraph_node *> targets;
unsigned int i; unsigned int i;
enum built_in_function fcode;
bool final; bool final;
if (TREE_CODE (TREE_TYPE (n->decl)) == FUNCTION_TYPE if (fndecl_built_in_p (n->decl, BUILT_IN_UNREACHABLE)
&& ((fcode = DECL_FUNCTION_CODE (n->decl)) == BUILT_IN_UNREACHABLE || fndecl_built_in_p (n->decl, BUILT_IN_TRAP))
|| fcode == BUILT_IN_TRAP))
return true; return true;
if (is_cxa_pure_virtual_p (n->decl)) if (is_cxa_pure_virtual_p (n->decl))
......
...@@ -3331,8 +3331,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, ...@@ -3331,8 +3331,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie,
if (can_refer) if (can_refer)
{ {
if (!t if (!t
|| (TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE || fndecl_built_in_p (t, BUILT_IN_UNREACHABLE)
&& DECL_FUNCTION_CODE (t) == BUILT_IN_UNREACHABLE)
|| !possible_polymorphic_call_target_p || !possible_polymorphic_call_target_p
(ie, cgraph_node::get (t))) (ie, cgraph_node::get (t)))
{ {
......
...@@ -3237,8 +3237,7 @@ expand_block_edges (struct tm_region *const region, basic_block bb) ...@@ -3237,8 +3237,7 @@ expand_block_edges (struct tm_region *const region, basic_block bb)
|| (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0) || (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0)
continue; continue;
if (DECL_FUNCTION_CODE (gimple_call_fndecl (call_stmt)) if (gimple_call_builtin_p (call_stmt, BUILT_IN_TM_ABORT))
== BUILT_IN_TM_ABORT)
{ {
// If we have a ``_transaction_cancel [[outer]]'', there is only // If we have a ``_transaction_cancel [[outer]]'', there is only
// one abnormal edge: to the transaction marked OUTER. // one abnormal edge: to the transaction marked OUTER.
......
...@@ -2598,7 +2598,7 @@ optimize_stack_restore (gimple_stmt_iterator i) ...@@ -2598,7 +2598,7 @@ optimize_stack_restore (gimple_stmt_iterator i)
|| ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee))) || ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (callee)))
return NULL_TREE; return NULL_TREE;
if (DECL_FUNCTION_CODE (callee) == BUILT_IN_STACK_RESTORE) if (fndecl_built_in_p (callee, BUILT_IN_STACK_RESTORE))
goto second_stack_restore; goto second_stack_restore;
} }
...@@ -2657,9 +2657,6 @@ optimize_stdarg_builtin (gimple *call) ...@@ -2657,9 +2657,6 @@ optimize_stdarg_builtin (gimple *call)
bool va_list_simple_ptr; bool va_list_simple_ptr;
location_t loc = gimple_location (call); location_t loc = gimple_location (call);
if (gimple_code (call) != GIMPLE_CALL)
return NULL_TREE;
callee = gimple_call_fndecl (call); callee = gimple_call_fndecl (call);
cfun_va_list = targetm.fn_abi_va_list (callee); cfun_va_list = targetm.fn_abi_va_list (callee);
......
...@@ -331,6 +331,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, ...@@ -331,6 +331,7 @@ record_temporary_equivalences_from_stmts_at_dest (edge e,
{ {
tree fndecl = gimple_call_fndecl (stmt); tree fndecl = gimple_call_fndecl (stmt);
if (fndecl if (fndecl
&& fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
&& (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)) || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P))
continue; continue;
......
...@@ -1297,7 +1297,7 @@ vect_recog_pow_pattern (stmt_vec_info stmt_vinfo, tree *type_out) ...@@ -1297,7 +1297,7 @@ vect_recog_pow_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
{ {
if (flag_unsafe_math_optimizations if (flag_unsafe_math_optimizations
&& TREE_CODE (base) == REAL_CST && TREE_CODE (base) == REAL_CST
&& !gimple_call_internal_p (last_stmt)) && gimple_call_builtin_p (last_stmt, BUILT_IN_NORMAL))
{ {
combined_fn log_cfn; combined_fn log_cfn;
built_in_function exp_bfn; built_in_function exp_bfn;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment