diff options
Diffstat (limited to 'gcc/gimple.c')
-rw-r--r-- | gcc/gimple.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/gcc/gimple.c b/gcc/gimple.c index afdf583..8d56a96 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -1548,6 +1548,57 @@ gimple_call_return_flags (const gcall *stmt) } +/* Return true if call STMT is known to return a non-zero result. */ + +bool +gimple_call_nonnull_result_p (gcall *call) +{ + tree fndecl = gimple_call_fndecl (call); + if (!fndecl) + return false; + if (flag_delete_null_pointer_checks && !flag_check_new + && DECL_IS_OPERATOR_NEW (fndecl) + && !TREE_NOTHROW (fndecl)) + return true; + + /* References are always non-NULL. */ + if (flag_delete_null_pointer_checks + && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE) + return true; + + if (flag_delete_null_pointer_checks + && lookup_attribute ("returns_nonnull", + TYPE_ATTRIBUTES (gimple_call_fntype (call)))) + return true; + return gimple_alloca_call_p (call); +} + + +/* If CALL returns a non-null result in an argument, return that arg. */ + +tree +gimple_call_nonnull_arg (gcall *call) +{ + tree fndecl = gimple_call_fndecl (call); + if (!fndecl) + return NULL_TREE; + + unsigned rf = gimple_call_return_flags (call); + if (rf & ERF_RETURNS_ARG) + { + unsigned argnum = rf & ERF_RETURN_ARG_MASK; + if (argnum < gimple_call_num_args (call)) + { + tree arg = gimple_call_arg (call, argnum); + if (SSA_VAR_P (arg) + && infer_nonnull_range_by_attribute (call, arg)) + return arg; + } + } + return NULL_TREE; +} + + /* Return true if GS is a copy assignment. */ bool |