C++: warn about missing return statement
Jason Merrill
jason@redhat.com
Tue Jul 4 00:44:00 GMT 2000
"Martin v. Loewis" <martin@mira.isdn.cs.tu-berlin.de> writes:
> 1999-11-23 Martin v. Löwis <loewis@informatik.hu-berlin.de>
>
> * decl.c (finish_function): Warn if a function has no return
> statement.
> Suggested by Andrew Koenig.
Thanks. I applied the following:
2000-07-04 Martin v. Löwis <loewis@informatik.hu-berlin.de>
Jason Merrill <jason@redhat.com>
* decl.c (finish_function): Warn if a function has no return
statement.
Suggested by Andrew Koenig.
* typeck.c (check_return_expr): Do set current_function_returns_value
if we got an error_mark_node.
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.650
diff -c -p -r1.650 decl.c
*** gcc/cp/decl.c 2000/07/02 08:07:55 1.650
--- gcc/cp/decl.c 2000/07/04 07:26:36
*************** finish_function (flags)
*** 14484,14513 ****
note_debug_info_needed (ctype);
#endif
! returns_null |= can_reach_end;
!
! /* Since we don't normally go through c_expand_return for constructors,
! this normally gets the wrong value.
! Also, named return values have their return codes emitted after
! NOTE_INSN_FUNCTION_END, confusing jump.c. */
! if (DECL_CONSTRUCTOR_P (fndecl)
! || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
! returns_null = 0;
if (TREE_THIS_VOLATILE (fndecl) && returns_null)
! cp_warning ("`noreturn' function `%D' does return", fndecl);
! else if ((warn_return_type || pedantic)
! && returns_null
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
{
! /* If this function returns non-void and control can drop through,
! complain. */
! cp_warning ("control reaches end of non-void function `%D'", fndecl);
! }
! /* With just -W, complain only if function returns both with
! and without a value. */
! else if (extra_warnings && returns_value && returns_null)
! warning ("this function may return with or without a value");
}
else
{
--- 14547,14570 ----
note_debug_info_needed (ctype);
#endif
! if (DECL_NAME (DECL_RESULT (fndecl)))
! returns_value |= can_reach_end;
! else
! returns_null |= can_reach_end;
if (TREE_THIS_VOLATILE (fndecl) && returns_null)
! warning ("`noreturn' function does return");
! else if (returns_null
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
{
! /* Always complain if there's just no return statement. */
! if (!returns_value)
! warning ("no return statement in function returning non-void");
! else if (warn_return_type || pedantic)
! /* If this function returns non-void and control can drop through,
! complain. */
! warning ("control reaches end of non-void function");
! }
}
else
{
Index: gcc/cp/typeck.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/typeck.c,v
retrieving revision 1.295
diff -c -p -r1.295 typeck.c
*** gcc/cp/typeck.c 2000/07/02 08:07:55 1.295
--- gcc/cp/typeck.c 2000/07/04 07:27:32
*************** check_return_expr (retval)
*** 6750,6778 ****
warning ("function declared `noreturn' has a `return' statement");
/* Check for various simple errors. */
! if (retval == error_mark_node)
{
- /* If an error occurred, there's nothing to do. */
- current_function_returns_null = 1;
- return error_mark_node;
- }
- else if (dtor_label)
- {
if (retval)
error ("returning a value from a destructor");
return NULL_TREE;
}
! else if (in_function_try_handler
! && DECL_CONSTRUCTOR_P (current_function_decl))
{
! /* If a return statement appears in a handler of the
! function-try-block of a constructor, the program is ill-formed. */
! error ("cannot return from a handler of a function-try-block of a constructor");
! return error_mark_node;
}
- else if (retval && DECL_CONSTRUCTOR_P (current_function_decl))
- /* You can't return a value from a constructor. */
- error ("returning a value from a constructor");
/* Under the old ABI, constructors actually always return `this',
even though in C++ you can't return a value from a constructor. */
--- 6750,6772 ----
warning ("function declared `noreturn' has a `return' statement");
/* Check for various simple errors. */
! if (dtor_label)
{
if (retval)
error ("returning a value from a destructor");
return NULL_TREE;
}
! else if (DECL_CONSTRUCTOR_P (current_function_decl))
{
! if (in_function_try_handler)
! /* If a return statement appears in a handler of the
! function-try-block of a constructor, the program is ill-formed. */
! error ("cannot return from a handler of a function-try-block of a constructor");
! else if (retval)
! /* You can't return a value from a constructor. */
! error ("returning a value from a constructor");
! return NULL_TREE;
}
/* Under the old ABI, constructors actually always return `this',
even though in C++ you can't return a value from a constructor. */
*************** check_return_expr (retval)
*** 6819,6824 ****
--- 6813,6821 ----
/* Remember that this function can sometimes return without a
value. */
current_function_returns_null = 1;
+ else
+ /* Remember that this function did return a value. */
+ current_function_returns_value = 1;
/* Only operator new(...) throw(), can return NULL [expr.new/13]. */
if ((DECL_OVERLOADED_OPERATOR_P (current_function_decl) == NEW_EXPR
*************** check_return_expr (retval)
*** 6836,6843 ****
/* We don't need to do any conversions when there's nothing being
returned. */
! if (!retval)
! return NULL_TREE;
/* Do any required conversions. */
if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
--- 6833,6840 ----
/* We don't need to do any conversions when there's nothing being
returned. */
! if (!retval || retval == error_mark_node)
! return retval;
/* Do any required conversions. */
if (retval == result || DECL_CONSTRUCTOR_P (current_function_decl))
*************** check_return_expr (retval)
*** 6858,6864 ****
/* If the conversion failed, treat this just like `return;'. */
if (retval == error_mark_node)
! return NULL_TREE;
/* We can't initialize a register from a AGGR_INIT_EXPR. */
else if (! current_function_returns_struct
&& TREE_CODE (retval) == TARGET_EXPR
--- 6855,6861 ----
/* If the conversion failed, treat this just like `return;'. */
if (retval == error_mark_node)
! return retval;
/* We can't initialize a register from a AGGR_INIT_EXPR. */
else if (! current_function_returns_struct
&& TREE_CODE (retval) == TARGET_EXPR
*************** check_return_expr (retval)
*** 6873,6880 ****
if (retval && retval != result)
retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
- /* All done. Remember that this function did return a value. */
- current_function_returns_value = 1;
return retval;
}
--- 6870,6875 ----
More information about the Gcc-patches
mailing list