[PATCH] Fix PR C++/19583, false warning with throw() functions

Ian Lance Taylor ian@airs.com
Thu Jan 27 02:42:00 GMT 2005


Andrew Pinski <pinskia@physics.uc.edu> writes:

> The problem here is that we warn about functions which have
> throw() on them even though the functions do return.  I thought
> there was an easy way to fix this would be add support to
> block_may_fallthru for TRY_CATCH_EXPR and EH_FILTER_EXPR but
> then I received an ICE so I decided to go a safer way in that
> we should skip through them when deciding if the function
> does warning about "control may reach end of non-void function".
> This fixed the bug easier and we don't have to support
> TRY_CATCH_EXPR and EH_FILTER_EXPR at all in block_may_fallthru.
> Even though this a band-aid, the original fix to add this
> warning is also a band-aid so I added a fixme so we know that
> this code can be just removed once merge in the tree-profiling
> branch.

Here is a patch which I like better.  Thanks to Andrew and RTH for
helping me understand how to write this.

I apologize for somehow overlooking the new C++ testsuite failures
eb132 and eb73.  I'm not sure how I missed those.  They are fixed by
this patch.

Is this patch OK if it passes the testsuite and bootstrap on
i686-pc-linux-gnu?

Ian


2005-01-26  Ian Lance Taylor  <ian@c2micro.com>

	PR middle-end/19583
	* gimple-low.c (try_catch_may_fallthru): New static function.
	(block_may_fallthru): Handle TRY_CATCH_EXPR.
	* tree-inline.c (expand_call_inline): Don't warn about reaching
	the end of a non-void function being inlined if the function uses
	a return slot.


Index: gimple-low.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.19
diff -p -u -r2.19 gimple-low.c
--- gimple-low.c	26 Jan 2005 03:18:06 -0000	2.19
+++ gimple-low.c	27 Jan 2005 02:31:21 -0000
@@ -263,6 +263,53 @@ lower_bind_expr (tree_stmt_iterator *tsi
   tsi_delink (tsi);
 }
 
+/* Try to determine whether a TRY_CATCH expression can fall through.
+   This is a subroutine of block_may_fallthru.  */
+
+static bool
+try_catch_may_fallthru (tree stmt)
+{
+  tree_stmt_iterator i;
+
+  /* If the TRY block can fall through, the whole TRY_CATCH can
+     fall through.  */
+  if (block_may_fallthru (TREE_OPERAND (stmt, 0)))
+    return true;
+
+  i = tsi_start (TREE_OPERAND (stmt, 1));
+  switch (TREE_CODE (tsi_stmt (i)))
+    {
+    case CATCH_EXPR:
+      /* We expect to see a sequence of CATCH_EXPR trees, each with a
+	 catch expression and a body.  The whole TRY_CATCH may fall
+	 through iff any of the catch bodies falls through.  */
+      for (; !tsi_end_p (i); tsi_next (&i))
+	{
+	  if (block_may_fallthru (CATCH_BODY (tsi_stmt (i))))
+	    return true;
+	}
+      return false;
+
+    case EH_FILTER_EXPR:
+      /* If the exception does not match EH_FILTER_TYPES, we will
+	 execute EH_FILTER_FAILURE, and we will fall through if that
+	 falls through.  If the exception does match EH_FILTER_TYPES,
+	 we will fall through.  We don't know which exceptions may be
+	 generated, so we just check for EH_FILTER_TYPES being NULL,
+	 in which case we know that that the exception does not
+	 match.  */
+      return (EH_FILTER_TYPES (tsi_stmt (i)) != NULL
+	      || block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i))));
+
+    default:
+      /* This case represents statements to be executed when an
+	 exception occurs.  Those statements are implicitly followed
+	 by a RESX_EXPR to resume execution after the exception.  So
+	 in this case the TRY_CATCH never falls through.  */
+      return false;
+    }
+}
+
 /* Try to determine if we can fall out of the bottom of BLOCK.  This guess
    need not be 100% accurate; simply be conservative and return true if we
    don't know.  This is used only to avoid stupidly generating extra code.
@@ -297,6 +344,9 @@ block_may_fallthru (tree block)
     case BIND_EXPR:
       return block_may_fallthru (BIND_EXPR_BODY (stmt));
 
+    case TRY_CATCH_EXPR:
+      return try_catch_may_fallthru (stmt);
+
     case TRY_FINALLY_EXPR:
       return block_may_fallthru (TREE_OPERAND (stmt, 1));
 
Index: tree-inline.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-inline.c,v
retrieving revision 1.169
diff -p -u -r1.169 tree-inline.c
--- tree-inline.c	26 Jan 2005 08:07:02 -0000	1.169
+++ tree-inline.c	27 Jan 2005 02:31:21 -0000
@@ -1616,9 +1616,13 @@ expand_call_inline (tree *tp, int *walk_
     id->current_node = edge->callee;
     copy = copy_body (id);
 
+    /* If the function uses a return slot, then it may legitimately
+       fall through while still returning a value, so we have to skip
+       the warning here.  */
     if (warn_return_type
 	&& !TREE_NO_WARNING (fn)
 	&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fn)))
+	&& return_slot_addr == NULL_TREE
 	&& block_may_fallthru (copy))
       {
 	warning ("control may reach end of non-void function %qD being inlined",



More information about the Gcc-patches mailing list