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