From efe49da0ba74c2fa1efe212d9c91cbdb1680c06d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 1 Feb 2002 14:32:51 -0500 Subject: [PATCH] re PR c++/4872 (missed warning (no return) -- regression from 2.95) 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 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/call.c | 3 +++ gcc/cp/cp-tree.h | 7 +++++++ gcc/cp/decl.c | 12 ++++++++++++ gcc/testsuite/g++.dg/abi/empty4.C | 2 +- gcc/testsuite/g++.dg/other/const2.C | 2 +- gcc/testsuite/g++.dg/other/deprecated.C | 4 ++-- gcc/testsuite/g++.old-deja/g++.bob/inherit2.C | 4 +++- gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C | 4 ++-- gcc/testsuite/g++.old-deja/g++.jason/byval2.C | 4 ++-- gcc/testsuite/g++.old-deja/g++.law/operators17.C | 6 +++--- gcc/testsuite/g++.old-deja/g++.mike/eh50.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/eh51.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/net20.C | 1 + gcc/testsuite/g++.old-deja/g++.mike/net40.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/net45.C | 3 +-- gcc/testsuite/g++.old-deja/g++.mike/p10511.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/p11012.C | 2 +- gcc/testsuite/g++.old-deja/g++.mike/p7325.C | 1 + gcc/testsuite/g++.old-deja/g++.other/crash25.C | 2 +- gcc/testsuite/g++.old-deja/g++.other/for1.C | 2 ++ gcc/testsuite/g++.old-deja/g++.other/init12.C | 2 +- gcc/testsuite/g++.old-deja/g++.other/new.C | 5 ++++- gcc/testsuite/g++.old-deja/g++.other/new4.C | 1 + gcc/testsuite/g++.old-deja/g++.other/rtti1.C | 6 +++--- gcc/testsuite/g++.old-deja/g++.pt/spec1.C | 2 +- 26 files changed, 64 insertions(+), 26 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index af18329d129..0bd68be0651 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2002-02-01 Jason Merrill + 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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cf6f0b42104..925bd067187 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f7cddacef7e..703720e9962 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a5d9c64767c..097b562281d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/testsuite/g++.dg/abi/empty4.C b/gcc/testsuite/g++.dg/abi/empty4.C index fe3d9a81a46..d20a55cf7fc 100644 --- a/gcc/testsuite/g++.dg/abi/empty4.C +++ b/gcc/testsuite/g++.dg/abi/empty4.C @@ -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;} }; diff --git a/gcc/testsuite/g++.dg/other/const2.C b/gcc/testsuite/g++.dg/other/const2.C index 25778fa73bc..86dde1e4559 100644 --- a/gcc/testsuite/g++.dg/other/const2.C +++ b/gcc/testsuite/g++.dg/other/const2.C @@ -10,7 +10,7 @@ struct foo static const bar bars[]; - int bad () + void bad () { this->*(bars[0].b) = 42; // { dg-bogus "read-only" "" } } diff --git a/gcc/testsuite/g++.dg/other/deprecated.C b/gcc/testsuite/g++.dg/other/deprecated.C index 40d9dba9c36..10560705031 100644 --- a/gcc/testsuite/g++.dg/other/deprecated.C +++ b/gcc/testsuite/g++.dg/other/deprecated.C @@ -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__)); diff --git a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C index fe9e73b95fa..a7aa4fe0adf 100644 --- a/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C +++ b/gcc/testsuite/g++.old-deja/g++.bob/inherit2.C @@ -1,11 +1,13 @@ // Build don't link: +#include + 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 { diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C b/gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C index a6249546d34..4c352c87ae4 100644 --- a/gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C +++ b/gcc/testsuite/g++.old-deja/g++.bugs/900205_03.C @@ -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 { diff --git a/gcc/testsuite/g++.old-deja/g++.jason/byval2.C b/gcc/testsuite/g++.old-deja/g++.jason/byval2.C index 490e625805d..62025813b32 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/byval2.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/byval2.C @@ -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]) { diff --git a/gcc/testsuite/g++.old-deja/g++.law/operators17.C b/gcc/testsuite/g++.old-deja/g++.law/operators17.C index 9c1a03b5531..7674233e688 100644 --- a/gcc/testsuite/g++.old-deja/g++.law/operators17.C +++ b/gcc/testsuite/g++.old-deja/g++.law/operators17.C @@ -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 - +}; diff --git a/gcc/testsuite/g++.old-deja/g++.mike/eh50.C b/gcc/testsuite/g++.old-deja/g++.mike/eh50.C index 84ccaddb9a9..702bbda7eac 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/eh50.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/eh50.C @@ -7,7 +7,7 @@ void my_unexpected() { throw 42; } -template int foo(T) throw (int) { throw "Hi"; } +template void foo(T) throw (int) { throw "Hi"; } main() { std::set_unexpected (my_unexpected); diff --git a/gcc/testsuite/g++.old-deja/g++.mike/eh51.C b/gcc/testsuite/g++.old-deja/g++.mike/eh51.C index 9ebeb4e8221..f1b90b42200 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/eh51.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/eh51.C @@ -7,7 +7,7 @@ void my_unexpected() { throw 42; } -template int foo(T) throw (T) { throw "Hi"; } +template void foo(T) throw (T) { throw "Hi"; } main() { std::set_unexpected (my_unexpected); diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net20.C b/gcc/testsuite/g++.old-deja/g++.mike/net20.C index 916ba434b37..731f6c149cc 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/net20.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/net20.C @@ -8,4 +8,5 @@ struct X void (X::* fee ())() { lab: goto lab; + return 0; } diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net40.C b/gcc/testsuite/g++.old-deja/g++.mike/net40.C index 10e16e685b7..db0df8a8678 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/net40.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/net40.C @@ -1,5 +1,5 @@ #include -extern "C" void abort(); +#include class toto { public: diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net45.C b/gcc/testsuite/g++.old-deja/g++.mike/net45.C index 388af8fe82f..fca48e9c295 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/net45.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/net45.C @@ -12,8 +12,7 @@ struct myint { } myint(const myint& mi) { } - myint& operator=(const myint& mi) { - } + myint& operator=(const myint& mi) { return *this; } }; extern pair a; diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p10511.C b/gcc/testsuite/g++.old-deja/g++.mike/p10511.C index b92b4f7d7fd..abe12e40d88 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/p10511.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/p10511.C @@ -8,7 +8,7 @@ public: class C { public: - bool f (S::E()) { } + bool f (S::E()) { return true; } virtual void foo(); }; diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p11012.C b/gcc/testsuite/g++.old-deja/g++.mike/p11012.C index aca77d42607..407c83a8fcb 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/p11012.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/p11012.C @@ -4,7 +4,7 @@ class Foo { public: - int f(){} + int f(){ return 0; } }; void foo() { diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p7325.C b/gcc/testsuite/g++.old-deja/g++.mike/p7325.C index e6d76f5321e..e481ccde0a6 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/p7325.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/p7325.C @@ -23,6 +23,7 @@ struct A { if (match_arg != &o) fail = 1; match_arg = &o; + return *this; } }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash25.C b/gcc/testsuite/g++.old-deja/g++.other/crash25.C index 2f471fb866f..0c39be8b0bd 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/crash25.C +++ b/gcc/testsuite/g++.old-deja/g++.other/crash25.C @@ -9,7 +9,7 @@ public: X::x() { // ERROR - -} +} // WARNING - no return X::~x() { // ERROR - diff --git a/gcc/testsuite/g++.old-deja/g++.other/for1.C b/gcc/testsuite/g++.old-deja/g++.other/for1.C index 31cd741a366..e737a41fa2a 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/for1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/for1.C @@ -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() { diff --git a/gcc/testsuite/g++.old-deja/g++.other/init12.C b/gcc/testsuite/g++.old-deja/g++.other/init12.C index ee0a029253a..9e4a4360157 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/init12.C +++ b/gcc/testsuite/g++.old-deja/g++.other/init12.C @@ -11,7 +11,7 @@ struct S struct T { - static int f() {} + static int f() { return 0; } }; static const S s = { &T::f }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/new.C b/gcc/testsuite/g++.old-deja/g++.other/new.C index e2839578d15..45187629a57 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/new.C +++ b/gcc/testsuite/g++.old-deja/g++.other/new.C @@ -1,13 +1,16 @@ // Build don't link: -typedef __SIZE_TYPE__ size_t; +#include + 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) diff --git a/gcc/testsuite/g++.old-deja/g++.other/new4.C b/gcc/testsuite/g++.old-deja/g++.other/new4.C index b9931b1caa5..2eb0954e741 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/new4.C +++ b/gcc/testsuite/g++.old-deja/g++.other/new4.C @@ -6,5 +6,6 @@ struct S { virtual int f() { new S[+f()]; + return 0; } }; diff --git a/gcc/testsuite/g++.old-deja/g++.other/rtti1.C b/gcc/testsuite/g++.old-deja/g++.other/rtti1.C index 7377e156dba..603c7d2311b 100644 --- a/gcc/testsuite/g++.old-deja/g++.other/rtti1.C +++ b/gcc/testsuite/g++.old-deja/g++.other/rtti1.C @@ -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;}; }; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec1.C b/gcc/testsuite/g++.old-deja/g++.pt/spec1.C index 7467293e145..ab18ff81c81 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/spec1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/spec1.C @@ -13,7 +13,7 @@ public: }; struct Operation { - double eval(double) {} + double eval(double) { return 0; } }; int main() {