[PATCH] Fix up -Wreturn-type (PR c++/83045)

Jakub Jelinek jakub@redhat.com
Tue Nov 21 13:57:00 GMT 2017


Hi!

The C++ FE now emits __builtin_unreachable () with BUILTINS_LOCATION
on spots that return from functions/methods returning non-void without
proper return.  This breaks the -Wreturn-type warning, because we then
don't see any return stmt without argument on the edges to exit, instead
we see those __builtin_unreachable () calls at the end of blocks without
successors.

I wonder if the C++ FE addition of __builtin_unreachable () shouldn't be
done only if (optimize).

Anyway, this patch tweaks tree-cfg.c so that it recognizes those
__builtin_unreachable () calls and reports the -Wreturn-type warning
in those cases too (warning in the FE would be too early, we need to
optimize away unreachable code).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

The patch regresses g++.dg/gomp/declare-simd-1.C, but given that it revealed
a real bug, I'm not trying to work around it in the patch and will fix it up
incrementally instead.

2017-11-21  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83045
	* tree-cfg.c (pass_warn_function_return::execute): Formatting fix.
	Also warn if seen __builtin_unreachable () call with BUILTINS_LOCATION.
	Use LOCATION_LOCUS when comparing against UNKNOWN_LOCATION.

	* c-c++-common/pr61405.c (fn0, fn1): Add return stmts.
	* c-c++-common/Wlogical-op-2.c (fn): Likewise.
	* g++.dg/debug/pr53466.C: Add -Wno-return-type to dg-options.
	* g++.dg/opt/combine.C: Likewise.
	* g++.dg/ubsan/return-3.C: Likewise.
	* g++.dg/pr59445.C: Likewise.
	* g++.dg/pr49847.C: Likewise.
	* g++.dg/ipa/pr61800.C: Likewise.
	* g++.dg/ipa/pr63470.C: Likewise.
	* g++.dg/ipa/pr68672-1.C: Likewise.
	* g++.dg/pr58438.C: Likewise.
	* g++.dg/torture/pr59265.C: Likewise.
	* g++.dg/tree-ssa/ssa-dse-2.C: Likewise.
	* g++.old-deja/g++.eh/catch13.C: Likewise.
	* g++.old-deja/g++.eh/crash1.C: Likewise.
	* g++.dg/tm/pr60004.C: Expect -Wreturn-type warning.
	* g++.dg/torture/pr55740.C: Likewise.
	* g++.dg/torture/pr43257.C: Likewise.
	* g++.dg/torture/pr64280.C: Likewise.
	* g++.dg/torture/pr54684.C: Likewise.
	* g++.dg/torture/pr56694.C: Likewise.
	* g++.dg/torture/pr68470.C: Likewise.
	* g++.dg/torture/pr60648.C: Likewise.
	* g++.dg/torture/pr71281.C: Likewise.
	* g++.dg/torture/pr52772.C: Add -Wno-return-type dg-additional-options.
	* g++.dg/torture/pr64669.C: Likewise.
	* g++.dg/torture/pr58369.C: Likewise.
	* g++.dg/torture/pr33627.C: Likewise.
	* g++.dg/torture/predcom-1.C: Add
	#pragma GCC diagnostic ignored "-Wreturn-type".
	* g++.dg/lto/20090221_0.C: Likewise.
	* g++.dg/lto/20091026-1_1.C: Likewise.
	* g++.dg/lto/pr54625-1_1.C: Likewise.
	* g++.dg/warn/pr83045.C: New test.

--- gcc/tree-cfg.c.jj	2017-11-20 19:55:36.723814204 +0100
+++ gcc/tree-cfg.c	2017-11-21 11:04:35.594567992 +0100
@@ -9049,7 +9049,8 @@ pass_warn_function_return::execute (func
 	  if ((gimple_code (last) == GIMPLE_RETURN
 	       || gimple_call_builtin_p (last, BUILT_IN_RETURN))
 	      && location == UNKNOWN_LOCATION
-	      && (location = gimple_location (last)) != UNKNOWN_LOCATION
+	      && ((location = LOCATION_LOCUS (gimple_location (last)))
+		  != UNKNOWN_LOCATION)
 	      && !optimize)
 	    break;
 	  /* When optimizing, replace return stmts in noreturn functions
@@ -9075,7 +9076,6 @@ pass_warn_function_return::execute (func
      without returning a value.  */
   else if (warn_return_type > 0
 	   && !TREE_NO_WARNING (fun->decl)
-	   && EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (fun)->preds) > 0
 	   && !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fun->decl))))
     {
       FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR_FOR_FN (fun)->preds)
@@ -9087,13 +9087,43 @@ pass_warn_function_return::execute (func
 	      && !gimple_no_warning_p (last))
 	    {
 	      location = gimple_location (last);
-	      if (location == UNKNOWN_LOCATION)
+	      if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
 		location = fun->function_end_locus;
-	      warning_at (location, OPT_Wreturn_type, "control reaches end of non-void function");
+	      warning_at (location, OPT_Wreturn_type,
+			  "control reaches end of non-void function");
 	      TREE_NO_WARNING (fun->decl) = 1;
 	      break;
 	    }
 	}
+      /* The C++ FE turns fallthrough from the end of non-void function
+	 into __builtin_unreachable () call with BUILTINS_LOCATION.
+	 Recognize those too.  */
+      basic_block bb;
+      if (!TREE_NO_WARNING (fun->decl))
+	FOR_EACH_BB_FN (bb, fun)
+	  if (EDGE_COUNT (bb->succs) == 0)
+	    {
+	      gimple *last = last_stmt (bb);
+	      if (last
+		  && (LOCATION_LOCUS (gimple_location (last))
+		      == BUILTINS_LOCATION)
+		  && gimple_call_builtin_p (last, BUILT_IN_UNREACHABLE))
+		{
+		  gimple_stmt_iterator gsi = gsi_for_stmt (last);
+		  gsi_prev_nondebug (&gsi);
+		  gimple *prev = gsi_stmt (gsi);
+		  if (prev == NULL)
+		    location = UNKNOWN_LOCATION;
+		  else
+		    location = gimple_location (prev);
+		  if (LOCATION_LOCUS (location) == UNKNOWN_LOCATION)
+		    location = fun->function_end_locus;
+		  warning_at (location, OPT_Wreturn_type,
+			      "control reaches end of non-void function");
+		  TREE_NO_WARNING (fun->decl) = 1;
+		  break;
+		}
+	    }
     }
   return 0;
 }
--- gcc/testsuite/c-c++-common/pr61405.c.jj	2014-09-25 08:40:33.000000000 +0200
+++ gcc/testsuite/c-c++-common/pr61405.c	2017-11-21 10:36:48.632950988 +0100
@@ -16,6 +16,7 @@ fn0 (struct S *s)
     case B:
       return 2;
     }
+  return 3;
 }
 
 int
@@ -28,4 +29,5 @@ fn1 (TS *s)
     case B:
       return 2;
     }
+  return 3;
 }
--- gcc/testsuite/c-c++-common/Wlogical-op-2.c.jj	2017-05-11 09:42:25.000000000 +0200
+++ gcc/testsuite/c-c++-common/Wlogical-op-2.c	2017-11-21 10:36:09.366433942 +0100
@@ -9,4 +9,5 @@ fn (int a, int b)
     return a;
   if ((a + 1) || (a + 1)) /* { dg-warning "logical .or. of equal expressions" } */
     return b;
+  return -1;
 }
--- gcc/testsuite/g++.dg/debug/pr53466.C.jj	2012-05-30 14:38:56.000000000 +0200
+++ gcc/testsuite/g++.dg/debug/pr53466.C	2017-11-21 10:31:35.176806840 +0100
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-foptimize-sibling-calls -fcompare-debug" }
+// { dg-options "-foptimize-sibling-calls -fcompare-debug -Wno-return-type" }
 
 typedef union gimple_statement_d *gimple;
 typedef gimple gimple_seq_node;
--- gcc/testsuite/g++.dg/opt/combine.C.jj	2017-11-06 17:23:29.000000000 +0100
+++ gcc/testsuite/g++.dg/opt/combine.C	2017-11-21 10:35:21.190026482 +0100
@@ -1,5 +1,5 @@
 // { dg-do assemble { target fpic } }
-// { dg-options "-O2 -fweb -fPIC -fvisibility=hidden" }
+// { dg-options "-O2 -fweb -fPIC -fvisibility=hidden -Wno-return-type" }
 // { dg-require-visibility "" }
 
 class QBasicAtomicInt
--- gcc/testsuite/g++.dg/ubsan/return-3.C.jj	2014-06-30 15:36:41.000000000 +0200
+++ gcc/testsuite/g++.dg/ubsan/return-3.C	2017-11-21 11:44:14.659408989 +0100
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-fsanitize=return" }
+// { dg-options "-fsanitize=return -Wno-return-type" }
 
 struct S { S (); ~S (); };
 
--- gcc/testsuite/g++.dg/tm/pr60004.C.jj	2014-01-31 22:22:02.000000000 +0100
+++ gcc/testsuite/g++.dg/tm/pr60004.C	2017-11-21 10:58:38.785906602 +0100
@@ -7,4 +7,4 @@ int f() {
         if (a == 5)
             return 1;
     }
-}
+}	// { dg-warning "control reaches end of non-void function" }
--- gcc/testsuite/g++.dg/pr59445.C.jj	2013-12-14 12:54:54.000000000 +0100
+++ gcc/testsuite/g++.dg/pr59445.C	2017-11-21 10:33:12.702606799 +0100
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -Wno-return-type" } */
 
 template <typename _Iterator> struct A;
 template <typename _Tp> struct A<_Tp *> {
--- gcc/testsuite/g++.dg/pr49847.C.jj	2014-03-03 08:24:12.000000000 +0100
+++ gcc/testsuite/g++.dg/pr49847.C	2017-11-21 10:32:07.166413212 +0100
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O -fnon-call-exceptions" } */
+/* { dg-options "-O -fnon-call-exceptions -Wno-return-type" } */
 int f (float g)
 {
   try { return g >= 0; }
--- gcc/testsuite/g++.dg/ipa/pr61800.C.jj	2014-09-08 22:12:49.000000000 +0200
+++ gcc/testsuite/g++.dg/ipa/pr61800.C	2017-11-21 10:33:48.363168195 +0100
@@ -1,7 +1,7 @@
 /* PR ipa/61800 */
 /* { dg-do compile } */
 /* { dg-require-visibility "" } */
-/* { dg-options "-O2" } */
+/* { dg-options "-O2 -Wno-return-type" } */
 
 #pragma GCC visibility push(hidden)
 class A
--- gcc/testsuite/g++.dg/ipa/pr63470.C.jj	2017-11-06 17:23:55.000000000 +0100
+++ gcc/testsuite/g++.dg/ipa/pr63470.C	2017-11-21 10:34:10.975890073 +0100
@@ -1,6 +1,6 @@
 /* PR ipa/63470.C */
 /* { dg-do compile } */
-/* { dg-options "-O2 -finline-functions" } */
+/* { dg-options "-O2 -finline-functions -Wno-return-type" } */
 
 class A
 {
--- gcc/testsuite/g++.dg/ipa/pr68672-1.C.jj	2016-02-12 12:57:18.000000000 +0100
+++ gcc/testsuite/g++.dg/ipa/pr68672-1.C	2017-11-21 10:34:55.532342056 +0100
@@ -1,6 +1,6 @@
 // PR ipa/68672
 // { dg-do compile }
-// { dg-options "-O -finline-small-functions -fpartial-inlining --param=partial-inlining-entry-probability=100" }
+// { dg-options "-O -finline-small-functions -fpartial-inlining --param=partial-inlining-entry-probability=100 -Wno-return-type" }
 
 void f2 (void *);
 void *a;
--- gcc/testsuite/g++.dg/pr58438.C.jj	2013-09-19 13:20:30.000000000 +0200
+++ gcc/testsuite/g++.dg/pr58438.C	2017-11-21 10:32:45.940936097 +0100
@@ -1,5 +1,5 @@
 /* { dg-do compile { target i?86-*-* x86_64-*-* } } */
-/* { dg-options "-march=amdfam10 -O3 -fprofile-generate" } */
+/* { dg-options "-march=amdfam10 -O3 -fprofile-generate -Wno-return-type" } */
 enum gimple_code {};
 struct A {
   gimple_code code;
--- gcc/testsuite/g++.dg/torture/pr55740.C.jj	2012-12-20 19:10:21.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr55740.C	2017-11-21 11:35:21.633993637 +0100
@@ -16,4 +16,4 @@ bool IsValidPath( char const * filename
       if ( *run ) 
 	++run;
     }
-}
+}	// { dg-warning "control reaches end of non-void function" }
--- gcc/testsuite/g++.dg/torture/pr52772.C.jj	2017-11-06 17:23:50.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr52772.C	2017-11-21 11:33:30.642365525 +0100
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-additional-options "-Wno-return-type" }
 
 typedef __SIZE_TYPE__ size_t;
 
--- gcc/testsuite/g++.dg/torture/pr43257.C.jj	2010-03-16 09:06:57.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr43257.C	2017-11-21 11:30:24.103671196 +0100
@@ -7,7 +7,7 @@ static void *func (int n)
 {
   void *p;
   if (p == 0) throw ::A ();
-}
+}	// { dg-warning "control reaches end of non-void function" }
 
 static void *func (int n, B const &)
 {
--- gcc/testsuite/g++.dg/torture/pr64280.C.jj	2015-12-16 09:02:08.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr64280.C	2017-11-21 11:39:56.060601647 +0100
@@ -39,4 +39,4 @@ F::m_fn2 ()
     else
       D ();
   A b;
-}
+}	// { dg-warning "control reaches end of non-void function" }
--- gcc/testsuite/g++.dg/torture/pr54684.C.jj	2013-06-01 14:47:21.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr54684.C	2017-11-21 11:34:46.567427070 +0100
@@ -60,4 +60,4 @@ bool visit_ref_for_mod_analysis (gimple
       ((void)(__builtin_expect(!(index >= 0), 0) ? __builtin_unreachable(), 0 : 0));
       ipa_set_param_used (info, index, true);
     }
-}
+}	// { dg-warning "control reaches end of non-void function" }
--- gcc/testsuite/g++.dg/torture/pr56694.C.jj	2013-04-02 20:24:33.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr56694.C	2017-11-21 11:36:30.401143656 +0100
@@ -20,7 +20,7 @@ inline GVector& GVector::operator+= (con
   if (m_num != v.m_num)
     throw GException::vector_mismatch(m_num, v.m_num);
   for (int i = 0; i < m_num; ++i)  m_data[i] += v.m_data[i];
-};
+};	// { dg-warning "control reaches end of non-void function" }
 void eval(GVector* m_gradient, GVector* vect_cpy_grad, int n)
 {
 #pragma omp sections
--- gcc/testsuite/g++.dg/torture/predcom-1.C.jj	2012-10-16 13:15:45.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/predcom-1.C	2017-11-21 11:43:31.231944472 +0100
@@ -1,6 +1,8 @@
 /* Test for ICE in predictive commoning with empty loop header block
    on arm-none-linux-*.  */
 
+#pragma GCC diagnostic ignored "-Wreturn-type"
+
 struct Foo
 {
   double *ptr;
--- gcc/testsuite/g++.dg/torture/pr64669.C.jj	2017-11-06 17:23:50.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr64669.C	2017-11-21 11:40:51.720913669 +0100
@@ -1,3 +1,5 @@
+// { dg-additional-options "-Wno-return-type" }
+
 typedef unsigned int source_location;
 typedef source_location location_t;
 extern void error_at (location_t, const char *, ...)
--- gcc/testsuite/g++.dg/torture/pr59265.C.jj	2015-06-30 14:08:38.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr59265.C	2017-11-21 11:38:14.931851627 +0100
@@ -1,5 +1,5 @@
 // { dg-do compile }
-// { dg-options "-fprofile-use -std=gnu++11" }
+// { dg-options "-fprofile-use -std=gnu++11 -Wno-return-type" }
 
 class A {
   int m_fn1() const;
--- gcc/testsuite/g++.dg/torture/pr68470.C.jj	2015-12-02 07:57:22.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr68470.C	2017-11-21 11:41:37.588346735 +0100
@@ -11,7 +11,7 @@ struct D {
     C *m_fn2() {
 	if (a)
 	  __builtin_abort();
-    }
+    }	// { dg-warning "control reaches end of non-void function" }
 };
 D getd();
 
--- gcc/testsuite/g++.dg/torture/pr58369.C.jj	2013-11-12 11:31:20.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr58369.C	2017-11-21 11:37:25.892457767 +0100
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-additional-options "-Wno-return-type" }
 // Reduced from boost-1.54
 
 int pow(int, int);
--- gcc/testsuite/g++.dg/torture/pr33627.C.jj	2017-11-06 17:23:50.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr33627.C	2017-11-21 11:00:49.833313133 +0100
@@ -1,4 +1,5 @@
 /* { dg-do compile } */
+/* { dg-additional-options "-Wno-return-type" } */
 
 typedef unsigned int UT_uint32;
 typedef UT_uint32 PT_DocPosition;
--- gcc/testsuite/g++.dg/torture/pr60648.C.jj	2014-03-29 12:05:44.000000000 +0100
+++ gcc/testsuite/g++.dg/torture/pr60648.C	2017-11-21 11:38:56.152342130 +0100
@@ -51,7 +51,7 @@ inline component fn2 (direction p1)
     case P:
       return component (3);
     }
-}
+}	// { dg-warning "control reaches end of non-void function" }
 
 void fn3 ()
 {
--- gcc/testsuite/g++.dg/torture/pr71281.C.jj	2016-06-07 14:56:41.000000000 +0200
+++ gcc/testsuite/g++.dg/torture/pr71281.C	2017-11-21 11:42:13.215906450 +0100
@@ -47,7 +47,7 @@ public:
     reference m_fn3(unsigned){
 	if (m_fn2())
 	  fn1();
-    }
+    }	// { dg-warning "control reaches end of non-void function" }
 };
 
 H<H<H<unsigned>>> c;
--- gcc/testsuite/g++.dg/lto/20090221_0.C.jj	2009-10-05 10:07:09.000000000 +0200
+++ gcc/testsuite/g++.dg/lto/20090221_0.C	2017-11-21 11:27:35.272757994 +0100
@@ -25,6 +25,7 @@ struct Baz
  Baz(Bar &a):a(a) { }
 };
 
+#pragma GCC diagnostic ignored "-Wreturn-type"
 struct Zonk
 {
  Baz baz;
--- gcc/testsuite/g++.dg/lto/20091026-1_1.C.jj	2009-11-04 08:15:17.000000000 +0100
+++ gcc/testsuite/g++.dg/lto/20091026-1_1.C	2017-11-21 11:27:15.416003429 +0100
@@ -1,4 +1,6 @@
 #include "20091026-1_a.h"
+
+#pragma GCC diagnostic ignored "-Wreturn-type"
 extern cHead networks;
 class cNetworkType;
 inline cNetworkType *findNetwork(const char *s)
--- gcc/testsuite/g++.dg/lto/pr54625-1_1.C.jj	2014-05-11 22:21:17.000000000 +0200
+++ gcc/testsuite/g++.dg/lto/pr54625-1_1.C	2017-11-21 11:28:07.741356673 +0100
@@ -1,5 +1,6 @@
 extern "C" double sin (double);
 typedef double UnaryFunType (double);
+#pragma GCC diagnostic ignored "-Wreturn-type"
 class A
 {
 public:
--- gcc/testsuite/g++.old-deja/g++.eh/catch13.C.jj	2008-09-05 12:54:57.000000000 +0200
+++ gcc/testsuite/g++.old-deja/g++.eh/catch13.C	2017-11-21 11:51:07.315320730 +0100
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "-O2" }
+// { dg-options "-O2 -Wno-return-type" }
 // Copyright (C) 2001 Free Software Foundation, Inc.
 // Contributed by Jakub Jelinek 2 May 2001 <jakub@redhat.com>
 
--- gcc/testsuite/g++.old-deja/g++.eh/crash1.C.jj	2008-09-05 12:54:57.000000000 +0200
+++ gcc/testsuite/g++.old-deja/g++.eh/crash1.C	2017-11-21 11:51:26.115088919 +0100
@@ -1,5 +1,5 @@
 // { dg-do assemble  }
-// { dg-options "-O1 -fno-inline-functions" }
+// { dg-options "-O1 -fno-inline-functions -Wno-return-type" }
 
 struct A
 {
--- gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C.jj	2017-05-12 14:34:48.000000000 +0200
+++ gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C	2017-11-21 14:38:25.336407998 +0100
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse2-details" } */
+/* { dg-options "-O2 -fdump-tree-dse2-details -Wno-return-type" } */
 
 typedef __SIZE_TYPE__ size_t;
 extern "C"
--- gcc/testsuite/g++.dg/warn/pr83045.C.jj	2017-11-21 09:55:55.273188978 +0100
+++ gcc/testsuite/g++.dg/warn/pr83045.C	2017-11-21 09:55:55.273188978 +0100
@@ -0,0 +1,19 @@
+// PR c++/83045
+// { dg-do compile }
+// { dg-options "-Wreturn-type -O2" }
+
+void foo (void);
+
+int
+bar (int a)
+{
+  if (a != 0)
+    foo ();
+}	/* { dg-warning "no return statement in function returning non-void" } */
+
+int
+baz (int a)
+{
+  if (a != 0)
+    __builtin_abort ();
+}	/* { dg-warning "control reaches end of non-void function" } */

	Jakub



More information about the Gcc-patches mailing list