re PR c++/4872 (missed warning (no return) -- regression from 2.95)
authorJason Merrill <jason@redhat.com>
Fri, 1 Feb 2002 19:32:51 +0000 (14:32 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 1 Feb 2002 19:32:51 +0000 (14:32 -0500)
        PR c++/4872
        * decl.c (finish_function): Warn about a non-void function with
        no return statement and no abnormal exit.
        * cp-tree.h (struct cp_language_function): Add returns_abnormally.
        (current_function_returns_abnormally): New macro.
        * call.c (build_call): Set it.

From-SVN: r49407

26 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/testsuite/g++.dg/abi/empty4.C
gcc/testsuite/g++.dg/other/const2.C
gcc/testsuite/g++.dg/other/deprecated.C
gcc/testsuite/g++.old-deja/g++.bob/inherit2.C
gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C
gcc/testsuite/g++.old-deja/g++.jason/byval2.C
gcc/testsuite/g++.old-deja/g++.law/operators17.C
gcc/testsuite/g++.old-deja/g++.mike/eh50.C
gcc/testsuite/g++.old-deja/g++.mike/eh51.C
gcc/testsuite/g++.old-deja/g++.mike/net20.C
gcc/testsuite/g++.old-deja/g++.mike/net40.C
gcc/testsuite/g++.old-deja/g++.mike/net45.C
gcc/testsuite/g++.old-deja/g++.mike/p10511.C
gcc/testsuite/g++.old-deja/g++.mike/p11012.C
gcc/testsuite/g++.old-deja/g++.mike/p7325.C
gcc/testsuite/g++.old-deja/g++.other/crash25.C
gcc/testsuite/g++.old-deja/g++.other/for1.C
gcc/testsuite/g++.old-deja/g++.other/init12.C
gcc/testsuite/g++.old-deja/g++.other/new.C
gcc/testsuite/g++.old-deja/g++.other/new4.C
gcc/testsuite/g++.old-deja/g++.other/rtti1.C
gcc/testsuite/g++.old-deja/g++.pt/spec1.C

index af18329d129c6ada4ccf7f1f60099351e02ed00a..0bd68be065134f68b0c68f84770a708a745a5195 100644 (file)
@@ -1,5 +1,12 @@
 2002-02-01  Jason Merrill  <jason@redhat.com>
 
+       PR c++/4872
+       * decl.c (finish_function): Warn about a non-void function with 
+       no return statement and no abnormal exit.
+       * cp-tree.h (struct cp_language_function): Add returns_abnormally.
+       (current_function_returns_abnormally): New macro.
+       * call.c (build_call): Set it.
+
        * typeck.c (build_component_ref): Always complain about offsetof
        constructs on non-PODs.  Only make it an error for members of
        virtual bases.
index cf6f0b4210408d8ddd27ee73e8bc13bb806f0172..925bd0671876d44b7339301fb6545468549e5bab 100644 (file)
@@ -408,6 +408,9 @@ build_call (function, parms)
   nothrow = ((decl && TREE_NOTHROW (decl))
             || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
 
+  if (decl && TREE_THIS_VOLATILE (decl))
+    current_function_returns_abnormally = 1;
+
   if (decl && TREE_DEPRECATED (decl))
     warn_deprecated_use (decl);
 
index f7cddacef7ee45c1f7b76dfbcf2c70dfd21e3180..703720e9962aaaa52e81750280a0379741fd60fd 100644 (file)
@@ -821,6 +821,7 @@ struct cp_language_function
 
   int returns_value;
   int returns_null;
+  int returns_abnormally;
   int in_function_try_handler;
   int x_expanding_p;
 
@@ -883,6 +884,12 @@ struct cp_language_function
 
 #define current_function_returns_null cp_function_chain->returns_null
 
+/* Set to 0 at beginning of a function definition, set to 1 if
+   a call to a noreturn function is seen.  */
+
+#define current_function_returns_abnormally \
+  cp_function_chain->returns_abnormally
+
 /* Non-zero if we should generate RTL for functions that we process.
    When this is zero, we just accumulate tree structure, without
    interacting with the back end.  */
index a5d9c64767cdae586e2cb614daa79e9de2b29113..097b562281ddcc8b5c56d2f68ac1114ca4c470ed 100644 (file)
@@ -14247,6 +14247,18 @@ finish_function (flags)
   if (!processing_template_decl && calls_setjmp_p (fndecl))
     DECL_UNINLINABLE (fndecl) = 1;
 
+  /* Complain if there's just no return statement.  */
+  if (!processing_template_decl
+      && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
+      && !current_function_returns_value
+      && !DECL_NAME (DECL_RESULT (fndecl))
+      /* Don't complain if we abort or throw.  */
+      && !current_function_returns_abnormally
+      /* If we have -Wreturn-type, let flow complain.  Unless we're an
+        inline function, as we might never be compiled separately.  */
+      && (!warn_return_type || DECL_INLINE (fndecl))
+    warning ("no return statement in function returning non-void");
+    
   /* Clear out memory we no longer need.  */
   free_after_parsing (cfun);
   /* Since we never call rest_of_compilation, we never clear
index fe3d9a81a46248fe3f0023b8abb138ee7e2c7687..d20a55cf7fcaa4c72156c251973d43c49d922a8f 100644 (file)
@@ -18,7 +18,7 @@ struct NonPod
 
   NonPod () {m = 0x12345678;}
   NonPod (long m_) {m = m_;}
-  NonPod &operator= (NonPod const &src) {now = m; m = src.m;}
+  NonPod &operator= (NonPod const &src) {now = m; m = src.m; return *this;}
   NonPod (NonPod const &src) {m = src.m;}
 };
 
index 25778fa73bcea5c77ee9193b089c9400787557d2..86dde1e4559c10d367a7691b4f7a9db9a685fcf8 100644 (file)
@@ -10,7 +10,7 @@ struct foo
 
   static const bar bars[];
 
-  int bad ()
+  void bad ()
   {
     this->*(bars[0].b) = 42; // { dg-bogus "read-only" "" }
   }
index 40d9dba9c36ca7efa128cf360179e10a9c322cd8..105607050312a67f4096171d6104e3425b110ef5 100644 (file)
@@ -13,10 +13,10 @@ INT1 should_be_unavailable;                 /* { dg-warning "`INT1' is deprecated" "" } */
 INT1a should_not_be_deprecated;
 
 INT1 f1(void) __attribute__ ((deprecated)); 
-INT1 f2(void) {}                       /* { dg-warning "`INT1' is deprecated" "" } */
+INT1 f2(void) { return 0; }            /* { dg-warning "`INT1' is deprecated" "" } */
 
 INT2 f3(void) __attribute__ ((__deprecated__)); 
-INT2 f4(void) {}                       /* { dg-warning "`INT2' is deprecated" "" } */
+INT2 f4(void) { return 0; }            /* { dg-warning "`INT2' is deprecated" "" } */
 int f5(INT2 x);                                /* { dg-warning "`INT2' is deprecated" "" } */
 int f6(INT2 x) __attribute__ ((__deprecated__));
 
index fe9e73b95fa1a605949cd63c531adb7348c6b903..a7aa4fe0adf2b663f788222e65ffc025cd3941ce 100644 (file)
@@ -1,11 +1,13 @@
 // Build don't link:
+#include <stdlib.h>
+
 class A {
 public:
   void z();
   A(void) {}
 private:
   A(const A &) { abort(); } // ERROR - 
-  const A& operator =(const A &) { abort(); } // WARNING - no return stmt XFAIL *-*-*
+  const A& operator =(const A &) { abort(); }
 };
 
 class B : public A {
index a6249546d341ad9723ca9a539acde039e7c96687..4c352c87ae43b37b07a4412c788cc795fcbb97e3 100644 (file)
@@ -25,10 +25,10 @@ struct00 global_function_1 () {
 struct struct0 {
 
   int struct0_member_function_0 () {
-  }                                    // ERROR - XFAIL
+  }                                    // ERROR - 
 
   struct0 struct0_member_function_1 () {
-  }                                    // ERROR - XFAIL
+  }                                    // ERROR - 
 };
 
 struct struct1 {
index 490e625805d9a862f21bca093d3d3f4a15ab889a..62025813b3285526fbcffad176a4e5d94ada4b7a 100644 (file)
@@ -13,8 +13,8 @@ public:
   void  operator -= (const Char   );
 };
 
-inline  Char  operator -  (const Char    a, const Char    b) {}
-inline  char  operator == (const Char    a, const char b) {}
+inline  Char  operator -  (const Char    a, const Char    b) { return Char(0); }
+inline  char  operator == (const Char    a, const char b) { return 0; }
 
 char mystrcmp(Char s[31], Char t[31])
 {
index 9c1a03b553167883b05dc8d83a7eb3f7037d7adf..7674233e688db44718e35fbf25afe1474138ee85 100644 (file)
@@ -7,6 +7,6 @@
 // Subject:  4 bugs in g++ 2.3.3
 // Message-ID: <9304291053.AA00090@mencon>
 
-        struct A {
-                A& operator = (const A& a) {}// ERROR - XFAIL
-        };
+struct A {
+        A& operator = (const A& a) {}// WARNING - 
+};
index 84ccaddb9a9e74f213ddc045b4a3545c672a2c67..702bbda7eac7364112c42b7e4d328b86bc19c7e8 100644 (file)
@@ -7,7 +7,7 @@ void my_unexpected() {
   throw 42;
 }
 
-template <class T> int foo(T) throw (int) { throw "Hi"; }
+template <class T> void foo(T) throw (int) { throw "Hi"; }
 
 main() {
   std::set_unexpected (my_unexpected);
index 9ebeb4e8221ad82d046c86033941ebb916476856..f1b90b422009c3935b3272f8237664f86bb1bfd7 100644 (file)
@@ -7,7 +7,7 @@ void my_unexpected() {
   throw 42;
 }
 
-template <class T> int foo(T) throw (T) { throw "Hi"; }
+template <class T> void foo(T) throw (T) { throw "Hi"; }
 
 main() {
   std::set_unexpected (my_unexpected);
index 916ba434b3772ba64dbd235f540d23748cd0aaaf..731f6c149cc769ca59b75309f7753b53ad97c207 100644 (file)
@@ -8,4 +8,5 @@ struct X
 void (X::* fee ())()
 {
  lab: goto lab;
+ return 0;
 }
index 10e16e685b75c74c4bd324b2d588466b220e759d..db0df8a867855db54215fcb378e2151347d0268e 100644 (file)
@@ -1,5 +1,5 @@
 #include <stddef.h>
-extern "C" void abort();
+#include <stdlib.h>
 
 class toto {
 public:
index 388af8fe82f9cabadc04cc489e0f339dd907b836..fca48e9c295089b79ca5cb40da5dcc710b52aec4 100644 (file)
@@ -12,8 +12,7 @@ struct myint {
   }
   myint(const myint& mi) {
   }
-  myint& operator=(const myint& mi) {
-  }
+  myint& operator=(const myint& mi) { return *this; }
 };
 
 extern pair<const myint, myint> a;
index b92b4f7d7fd02ddbda43091f200737876e5998a8..abe12e40d88fb9e0d61d9e4ab49995ab180be5b9 100644 (file)
@@ -8,7 +8,7 @@ public:
 
 class C {
 public:
-  bool f (S::E()) { }
+  bool f (S::E()) { return true; }
   virtual void foo();
 };
 
index aca77d42607653423c2c17c53faebfd6e38f8d1d..407c83a8fcb9f70f1b9490f1067c8065816987ce 100644 (file)
@@ -4,7 +4,7 @@
 
 class Foo {
 public:
-  int f(){}
+  int f(){ return 0; }
 };
 
 void foo() {
index e6d76f5321e03f1ea7b4d660ed49efd320fc756c..e481ccde0a64c447e3b5e4d828b8e96d7aee1e75 100644 (file)
@@ -23,6 +23,7 @@ struct A {
       if (match_arg != &o)
        fail = 1;
     match_arg = &o;
+    return *this;
   }
 };
 
index 2f471fb866f99b5e67ccb2cdc277bde091aefe58..0c39be8b0bd7567366fcc1a1a1bc1d1e9408887f 100644 (file)
@@ -9,7 +9,7 @@ public:
 
 X::x()
 {                              // ERROR - 
-}
+} // WARNING - no return
 
 X::~x()
 {                              // ERROR - 
index 31cd741a366878800af45862b17765f16d29bfae..e737a41fa2a14187427419a47b4794c0bb2a65c9 100644 (file)
@@ -7,6 +7,7 @@ struct S {
   int operator()(int)
     {
       i = 1;
+      return i;
     }
 
   typedef int I;
@@ -24,6 +25,7 @@ struct T {
   int operator()(int)
     {
       j = 1;
+      return j;
     }
 
   void f() {
index ee0a029253aee103329502ac96acdb1807165c3d..9e4a436015776c8b6ab8fee2341597e4b3942e34 100644 (file)
@@ -11,7 +11,7 @@ struct S
 
 struct T
 {
-  static int f() {}
+  static int f() { return 0; }
 };
 
 static const S s = { &T::f };
index e2839578d15d8d83c5f60733950273ef8c535bff..45187629a5704e61fc6e9d3eda668bce0caee23d 100644 (file)
@@ -1,13 +1,16 @@
 // Build don't link:
 
-typedef __SIZE_TYPE__ size_t;
+#include <new>
+
 inline void *
 operator new(size_t alloc_sz, const char *fname, unsigned lineno)
 {
+  return ::operator new (alloc_sz);
 }
 inline void *
 operator new[](size_t alloc_sz, const char *fname, unsigned lineno) 
 {
+  return ::operator new[] (alloc_sz);
 }
 inline void
 operator delete(void *ptr, const char *fname, unsigned lineno) 
index b9931b1caa53d412aae5b01cedbb46dd63b7a124..2eb0954e741c6ac04ce71be05b146b7f18d6d939 100644 (file)
@@ -6,5 +6,6 @@ struct S {
 
   virtual int f() {
     new S[+f()];
+    return 0;
   }
 };
index 7377e156dba5ebb1fbf280a11137ad3aa16f8f33..603c7d2311b4c8256d5519acc0bfa1feff279592 100644 (file)
@@ -39,15 +39,15 @@ class XX {
 public:
   int xxi;
   float xxf;
-  int xxf1 () {};
-  int xxf2 (int k) {};
+  int xxf1 () { return 0; };
+  int xxf2 (int k) { return 0; };
 };
 
 class YY {
 public:
   int yyi;
   double yyd;
-  int yyf1 (float f) {};
+  int yyf1 (float f) { return 0; };
   double yyf2 () {return yyd;};
 };
 
index 7467293e14580984b37b078136b1155d2387956a..ab18ff81c81a01d6291f05bd661b6f3b3ab7daad 100644 (file)
@@ -13,7 +13,7 @@ public:
 };
 
 struct Operation {
-  double eval(double) {}
+  double eval(double) { return 0; }
 };
 
 int main() {