[PATCH] PR17544, a C99 and C++ Wunreachable-code problem

Steven Bosscher stevenb@suse.de
Fri Dec 31 12:01:00 GMT 2004


Hi,

This patch is marked "middle-end", but really it's a problem in the
middle-end *and* the front ends.  There was no way to mark a complete
statement as compiler generated in a way that would survive through
gimplification, and the gimplifier would notice that some statements
do not have a source location.

In this particular case, the "return 0;" statement required in C99
mode and by C++ would get annotated with a locus by the gimplifier.

But often the compiler generated "return 0;" is not reachable.  The
-Wunreachable-code warnings only happen for statements with a source
location, and since the compiler generated statement got a locus in
the gimplifier, we warn if they're unreachable.

My proposed fix is to put a locus on the compiler generated statement
in the front end: just put it in the current file, on line 0.  Then
teach the places where we issue unreachable code warnings to issue
the warning only if the unreachable code is on a line number >0.

The attached patch was bootstrapped and tested (all except Ada) on
x86_64-suse-linux-gnu, and it fixes PR17544, a regression from all
earlier GCC releases.  OK to apply?

Gr.
Steven


	PR middle-end/17544
	* c-decl.c (finish_function): If compiling C99, annotate the
	compiler generated return with the current file name and line 0.
	* tree-cfg.c (remove_useless_stmts_warn_notreached): Only warn if
	the source line is greater than 0.
	(remove_bb): Likewise.

cp/
	PR middle-end/17544
	* decl.c (finish_function): Fix comment.  Annotate the compiler
	generated return with the current file name and line 0.

testsuite/
	* gcc.dg/20041231-1.C: New test.
	* g++.dg/warn/Wunreachable-code-1.C: New test.


Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.619
diff -c -3 -p -r1.619 c-decl.c
*** c-decl.c	21 Dec 2004 17:06:25 -0000	1.619
--- c-decl.c	31 Dec 2004 11:47:54 -0000
*************** Software Foundation, 59 Temple Place - S
*** 29,34 ****
--- 29,35 ----
  #include "config.h"
  #include "system.h"
  #include "coretypes.h"
+ #include "input.h"
  #include "tm.h"
  #include "intl.h"
  #include "tree.h"
*************** finish_function (void)
*** 6286,6292 ****
        else
  	{
  	  if (flag_isoc99)
! 	    c_finish_return (integer_zero_node);
  	}
      }
  
--- 6287,6299 ----
        else
  	{
  	  if (flag_isoc99)
! 	    {
! 	      tree stmt = c_finish_return (integer_zero_node);
! 	      /* Hack.  We don't want the middle-end to warn that this
! 		 return is unreachable, so put the statement on the
! 		 special line 0.  */
! 	      annotate_with_file_line (stmt, input_filename, 0);
! 	    }
  	}
      }
  
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.136
diff -c -3 -p -r2.136 tree-cfg.c
*** tree-cfg.c	13 Dec 2004 16:06:23 -0000	2.136
--- tree-cfg.c	31 Dec 2004 11:47:54 -0000
*************** remove_useless_stmts_warn_notreached (tr
*** 1323,1330 ****
    if (EXPR_HAS_LOCATION (stmt))
      {
        location_t loc = EXPR_LOCATION (stmt);
!       warning ("%Hwill never be executed", &loc);
!       return true;
      }
  
    switch (TREE_CODE (stmt))
--- 1323,1333 ----
    if (EXPR_HAS_LOCATION (stmt))
      {
        location_t loc = EXPR_LOCATION (stmt);
!       if (LOCATION_LINE (loc) > 0)
! 	{
! 	  warning ("%Hwill never be executed", &loc);
! 	  return true;
! 	}
      }
  
    switch (TREE_CODE (stmt))
*************** remove_bb (basic_block bb)
*** 2021,2031 ****
  	 since this way we lose warnings for gotos in the original
  	 program that are indeed unreachable.  */
        if (TREE_CODE (stmt) != GOTO_EXPR && EXPR_HAS_LOCATION (stmt) && !loc)
  #ifdef USE_MAPPED_LOCATION
! 	loc = EXPR_LOCATION (stmt);
  #else
! 	loc = EXPR_LOCUS (stmt);
  #endif
      }
  
    /* If requested, give a warning that the first statement in the
--- 2024,2040 ----
  	 since this way we lose warnings for gotos in the original
  	 program that are indeed unreachable.  */
        if (TREE_CODE (stmt) != GOTO_EXPR && EXPR_HAS_LOCATION (stmt) && !loc)
+ 	{
+ 	  source_locus t;
+ 
  #ifdef USE_MAPPED_LOCATION
! 	  t = EXPR_LOCATION (stmt);
  #else
! 	  t = EXPR_LOCUS (stmt);
  #endif
+ 	  if (t && LOCATION_LINE (*t) > 0)
+ 	    loc = t;
+ 	}
      }
  
    /* If requested, give a warning that the first statement in the
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1349
diff -c -3 -p -r1.1349 decl.c
*** cp/decl.c	30 Dec 2004 23:29:30 -0000	1.1349
--- cp/decl.c	31 Dec 2004 11:47:56 -0000
*************** finish_function (int flags)
*** 10635,10646 ****
      {
        if (DECL_MAIN_P (current_function_decl))
  	{
! 	  /* Make it so that `main' always returns 0 by default.  */
  #if VMS_TARGET
! 	  finish_return_stmt (integer_one_node);
  #else
! 	  finish_return_stmt (integer_zero_node);
  #endif
  	}
  
        /* Finish dealing with exception specifiers.  */
--- 10635,10653 ----
      {
        if (DECL_MAIN_P (current_function_decl))
  	{
! 	  tree stmt;
! 
! 	  /* Make it so that `main' always returns 0 by default (or
! 	     1 for VMS).  */
  #if VMS_TARGET
! 	  stmt = finish_return_stmt (integer_one_node);
  #else
! 	  stmt = finish_return_stmt (integer_zero_node);
  #endif
+ 	  /* Hack.  We don't want the middle-end to warn that this
+ 	     return is unreachable, so put the statement on the
+ 	     special line 0.  */
+ 	  annotate_with_file_line (stmt, input_filename, 0);
  	}
  
        /* Finish dealing with exception specifiers.  */
Index: testsuite/g++.dg/warn/Wunreachable-code-1.C
===================================================================
RCS file: testsuite/g++.dg/warn/Wunreachable-code-1.C
diff -N testsuite/g++.dg/warn/Wunreachable-code-1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/warn/Wunreachable-code-1.C	31 Dec 2004 11:47:57 -0000
***************
*** 0 ****
--- 1,22 ----
+ /* PR17544 Incorrect -Wunreachable-code warning
+    Origin: sebor@roguewave.com
+ 
+    G++ appends a "return 0;" when finishing a function, but it was not
+    given a source location.  The gimplifier thinks a return statement
+    needs a locus so it would add one, making the compiler generated code
+    visible to the unreachable code warning.  */
+ 
+ /* { dg-do compile } */
+ /* { dg-options "-O -Wunreachable-code" } */
+ 
+ int
+ main (int argc, char *argv[])
+ {
+   const char* const s = argc < 2 ? "" : argv [1];
+   int i = 0;
+   do {
+     ++i;
+   } while (i < s [0]);
+   return i;
+ }
+ 
Index: testsuite/gcc.dg/20041231-1.c
===================================================================
RCS file: testsuite/gcc.dg/20041231-1.c
diff -N testsuite/gcc.dg/20041231-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/20041231-1.c	31 Dec 2004 11:47:57 -0000
***************
*** 0 ****
--- 1,15 ----
+ /* PR17544 Incorrect -Wunreachable-code warning
+    Origin: Giovanni Bajo
+ 
+    In C99 we append a "return 0;" when finishing a function, but it was
+    not given a source location.  The gimplifier thinks a return statement
+    needs a locus so it would add one, making the compiler generated code
+    visible to the unreachable code warning.  */
+ 
+ /* { dg-do compile } */
+ /* { dg-options "-std=c99 -O -Wunreachable-code" } */
+ 
+ int main (void)    // 1
+ {                  // 2
+   return 0;        // 3
+ }                  // 4



More information about the Gcc-patches mailing list