===================================================================
@@ -2710,6 +2710,15 @@ DEFHOOK
void, (struct hard_reg_set_container *),
NULL)
+/* For targets that have attributes that can affect whether a
+ function's return statements need checking. For instance a 'naked'
+ function attribute. */
+DEFHOOK
+(warn_func_return,
+ "True if a function's return statements should be checked for matching the function's return type. This includes checking for falling off the end of a non-void function. Return false if no such check should be made.",
+ bool, (tree),
+ hook_bool_tree_true)
+
/* Determine the type of unwind info to emit for debugging. */
DEFHOOK
(debug_unwind_info,
===================================================================
@@ -4918,6 +4918,8 @@ FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM
@hook TARGET_SET_UP_BY_PROLOGUE
+@hook TARGET_WARN_FUNC_RETURN
+
@node Stack Smashing Protection
@subsection Stack smashing protection
@cindex stack smashing protection
===================================================================
@@ -4977,6 +4977,10 @@ FRAME_POINTER_REGNUM, ARG_POINTER_REGNUM
This hook should add additional registers that are computed by the prologue to the hard regset for shrink-wrapping optimization purposes.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_WARN_FUNC_RETURN (tree)
+True if a function's return statements should be checked for matching the function's return type. This includes checking for falling off the end of a non-void function. Return false if no such check should be made.
+@end deftypefn
+
@node Stack Smashing Protection
@subsection Stack smashing protection
@cindex stack smashing protection
===================================================================
@@ -1782,6 +1782,9 @@ Target keeps null pointer checks, either
@item lto
Compiler has been configured to support link-time optimization (LTO).
+@item naked_functions
+Target supports the @code{naked} function attribute.
+
@item named_sections
Target supports named sections.
===================================================================
@@ -186,7 +186,8 @@ void
warn_function_noreturn (tree decl)
{
static struct pointer_set_t *warned_about;
- if (!lang_hooks.missing_noreturn_ok_p (decl))
+ if (!lang_hooks.missing_noreturn_ok_p (decl)
+ && targetm.warn_func_return (decl))
warned_about
= suggest_attribute (OPT_Wsuggest_attribute_noreturn, decl,
true, warned_about, "noreturn");
===================================================================
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.
#include "value-prof.h"
#include "pointer-set.h"
#include "tree-inline.h"
+#include "target.h"
/* This file contains functions for building the Control Flow Graph (CFG)
for a function tree. */
@@ -7613,6 +7614,9 @@ execute_warn_function_return (void)
edge e;
edge_iterator ei;
+ if (!targetm.warn_func_return (cfun->decl))
+ return 0;
+
/* If we have a path to EXIT, then we do return. */
if (TREE_THIS_VOLATILE (cfun->decl)
&& EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0)
===================================================================
@@ -5881,6 +5881,14 @@ spu_trampoline_init (rtx m_tramp, tree f
emit_insn (gen_sync ());
}
+static bool
+spu_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !spu_naked_function_p (decl);
+}
+
void
spu_expand_sign_extend (rtx ops[])
{
@@ -7267,6 +7275,9 @@ static const struct attribute_spec spu_a
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT spu_trampoline_init
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN spu_warn_func_return
+
#undef TARGET_OPTION_OVERRIDE
#define TARGET_OPTION_OVERRIDE spu_option_override
===================================================================
@@ -2629,6 +2629,14 @@ rx_func_attr_inlinable (const_tree decl)
&& ! is_naked_func (decl);
}
+static bool
+rx_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !is_naked_func (decl);
+}
+
/* Return nonzero if it is ok to make a tail-call to DECL,
a function_decl or NULL if this is an indirect call, using EXP */
@@ -3282,6 +3290,9 @@ rx_adjust_insn_length (rtx insn, int cur
#undef TARGET_LEGITIMIZE_ADDRESS
#define TARGET_LEGITIMIZE_ADDRESS rx_legitimize_address
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN rx_warn_func_return
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-rx.h"
===================================================================
@@ -686,6 +686,17 @@ avr_can_eliminate (const int from, const
&& !frame_pointer_needed));
}
+
+/* Implement TARGET_WARN_FUNC_RETURN. */
+
+static bool
+avr_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return !avr_naked_function_p (decl);
+}
+
/* Compute offset between arg_pointer and frame_pointer. */
int
@@ -10790,6 +10801,9 @@ avr_fold_builtin (tree fndecl, int n_arg
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE avr_can_eliminate
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN avr_warn_func_return
+
#undef TARGET_CLASS_LIKELY_SPILLED_P
#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
===================================================================
@@ -236,6 +236,7 @@ static int arm_issue_rate (void);
static void arm_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static bool arm_output_addr_const_extra (FILE *, rtx);
static bool arm_allocate_stack_slots_for_args (void);
+static bool arm_warn_func_return (tree);
static const char *arm_invalid_parameter_type (const_tree t);
static const char *arm_invalid_return_type (const_tree t);
static tree arm_promoted_type (const_tree t);
@@ -458,6 +459,9 @@ static const struct attribute_spec arm_a
#undef TARGET_TRAMPOLINE_ADJUST_ADDRESS
#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arm_trampoline_adjust_address
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN arm_warn_func_return
+
#undef TARGET_DEFAULT_SHORT_ENUMS
#define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
@@ -2168,6 +2172,14 @@ arm_allocate_stack_slots_for_args (void)
return !IS_NAKED (arm_current_func_type ());
}
+static bool
+arm_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE;
+}
+
/* Output assembler code for a block containing the constant parts
of a trampoline, leaving space for the variable parts.
===================================================================
@@ -138,6 +138,7 @@ static unsigned int mcore_function_arg_b
const_tree);
static void mcore_asm_trampoline_template (FILE *);
static void mcore_trampoline_init (rtx, tree, rtx);
+static bool mcore_warn_func_return (tree);
static void mcore_option_override (void);
static bool mcore_legitimate_constant_p (enum machine_mode, rtx);
@@ -228,6 +229,9 @@ static const struct attribute_spec mcore
#undef TARGET_LEGITIMATE_CONSTANT_P
#define TARGET_LEGITIMATE_CONSTANT_P mcore_legitimate_constant_p
+#undef TARGET_WARN_FUNC_RETURN
+#define TARGET_WARN_FUNC_RETURN mcore_warn_func_return
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Adjust the stack and return the number of bytes taken to do it. */
@@ -2580,9 +2584,6 @@ conditionalize_optimization (void)
continue;
}
-static int saved_warn_return_type = -1;
-static int saved_warn_return_type_count = 0;
-
/* This is to handle loads from the constant pool. */
static void
@@ -2591,21 +2592,6 @@ mcore_reorg (void)
/* Reset this variable. */
current_function_anonymous_args = 0;
- /* Restore the warn_return_type if it has been altered. */
- if (saved_warn_return_type != -1)
- {
- /* Only restore the value if we have reached another function.
- The test of warn_return_type occurs in final_function () in
- c-decl.c a long time after the code for the function is generated,
- so we need a counter to tell us when we have finished parsing that
- function and can restore the flag. */
- if (--saved_warn_return_type_count == 0)
- {
- warn_return_type = saved_warn_return_type;
- saved_warn_return_type = -1;
- }
- }
-
if (optimize == 0)
return;
@@ -3056,25 +3042,7 @@ static tree
mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
{
- if (TREE_CODE (*node) == FUNCTION_DECL)
- {
- /* PR14310 - don't complain about lack of return statement
- in naked functions. The solution here is a gross hack
- but this is the only way to solve the problem without
- adding a new feature to GCC. I did try submitting a patch
- that would add such a new feature, but it was (rightfully)
- rejected on the grounds that it was creeping featurism,
- so hence this code. */
- if (warn_return_type)
- {
- saved_warn_return_type = warn_return_type;
- warn_return_type = 0;
- saved_warn_return_type_count = 2;
- }
- else if (saved_warn_return_type_count)
- saved_warn_return_type_count = 2;
- }
- else
+ if (TREE_CODE (*node) != FUNCTION_DECL)
{
warning (OPT_Wattributes, "%qE attribute only applies to functions",
name);
@@ -3126,6 +3094,14 @@ mcore_naked_function_p (void)
return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
}
+static bool
+mcore_warn_func_return (tree decl)
+{
+ /* Naked functions are implemented entirely in assembly, including the
+ return sequence, so suppress warnings about this. */
+ return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE;
+}
+
#ifdef OBJECT_FORMAT_ELF
static void
mcore_asm_named_section (const char *name,
===================================================================
@@ -13588,7 +13588,8 @@ finish_function (int flags)
&& !TREE_NO_WARNING (fndecl)
/* Structor return values (if any) are set by the compiler. */
&& !DECL_CONSTRUCTOR_P (fndecl)
- && !DECL_DESTRUCTOR_P (fndecl))
+ && !DECL_DESTRUCTOR_P (fndecl)
+ && targetm.warn_func_return (fndecl))
{
warning (OPT_Wreturn_type,
"no return statement in function returning non-void");
===================================================================
@@ -984,6 +984,14 @@ proc check_named_sections_available { }
}]
}
+# Return true if the "naked" function attribute is supported on this target.
+
+proc check_effective_target_naked_functions { } {
+ return [check_no_compiler_messages naked_functions assembly {
+ void f() __attribute__((naked));
+ }]
+}
+
# Return 1 if the target supports Fortran real kinds larger than real(8),
# 0 otherwise.
#
===================================================================
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target naked_functions } */
+/* { dg-options "-O2 -Wall" } */
+/* Check that we do not get warnings about missing return statements
+ or bogus looking noreturn functions. */
+int __attribute__((naked))
+foo(void)
+{
+ __asm__ volatile ("mov r0, #1\r\nbx lr\n");
+}
+
+int __attribute__((naked,noreturn))
+bar(void)
+{
+ __asm__ volatile ("frob r0\n");
+}