Commit efe49da0 by Jason Merrill Committed by Jason Merrill

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
parent f2d9afec
2002-02-01 Jason Merrill <jason@redhat.com> 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 * typeck.c (build_component_ref): Always complain about offsetof
constructs on non-PODs. Only make it an error for members of constructs on non-PODs. Only make it an error for members of
virtual bases. virtual bases.
......
...@@ -408,6 +408,9 @@ build_call (function, parms) ...@@ -408,6 +408,9 @@ build_call (function, parms)
nothrow = ((decl && TREE_NOTHROW (decl)) nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function)))); || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
if (decl && TREE_THIS_VOLATILE (decl))
current_function_returns_abnormally = 1;
if (decl && TREE_DEPRECATED (decl)) if (decl && TREE_DEPRECATED (decl))
warn_deprecated_use (decl); warn_deprecated_use (decl);
......
...@@ -821,6 +821,7 @@ struct cp_language_function ...@@ -821,6 +821,7 @@ struct cp_language_function
int returns_value; int returns_value;
int returns_null; int returns_null;
int returns_abnormally;
int in_function_try_handler; int in_function_try_handler;
int x_expanding_p; int x_expanding_p;
...@@ -883,6 +884,12 @@ struct cp_language_function ...@@ -883,6 +884,12 @@ struct cp_language_function
#define current_function_returns_null cp_function_chain->returns_null #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. /* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without When this is zero, we just accumulate tree structure, without
interacting with the back end. */ interacting with the back end. */
......
...@@ -14247,6 +14247,18 @@ finish_function (flags) ...@@ -14247,6 +14247,18 @@ finish_function (flags)
if (!processing_template_decl && calls_setjmp_p (fndecl)) if (!processing_template_decl && calls_setjmp_p (fndecl))
DECL_UNINLINABLE (fndecl) = 1; 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. */ /* Clear out memory we no longer need. */
free_after_parsing (cfun); free_after_parsing (cfun);
/* Since we never call rest_of_compilation, we never clear /* Since we never call rest_of_compilation, we never clear
......
...@@ -18,7 +18,7 @@ struct NonPod ...@@ -18,7 +18,7 @@ struct NonPod
NonPod () {m = 0x12345678;} NonPod () {m = 0x12345678;}
NonPod (long m_) {m = m_;} 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;} NonPod (NonPod const &src) {m = src.m;}
}; };
......
...@@ -10,7 +10,7 @@ struct foo ...@@ -10,7 +10,7 @@ struct foo
static const bar bars[]; static const bar bars[];
int bad () void bad ()
{ {
this->*(bars[0].b) = 42; // { dg-bogus "read-only" "" } this->*(bars[0].b) = 42; // { dg-bogus "read-only" "" }
} }
......
...@@ -13,10 +13,10 @@ INT1 should_be_unavailable; /* { dg-warning "`INT1' is deprecated" "" } */ ...@@ -13,10 +13,10 @@ INT1 should_be_unavailable; /* { dg-warning "`INT1' is deprecated" "" } */
INT1a should_not_be_deprecated; INT1a should_not_be_deprecated;
INT1 f1(void) __attribute__ ((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 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 f5(INT2 x); /* { dg-warning "`INT2' is deprecated" "" } */
int f6(INT2 x) __attribute__ ((__deprecated__)); int f6(INT2 x) __attribute__ ((__deprecated__));
......
// Build don't link: // Build don't link:
#include <stdlib.h>
class A { class A {
public: public:
void z(); void z();
A(void) {} A(void) {}
private: private:
A(const A &) { abort(); } // ERROR - 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 { class B : public A {
......
...@@ -25,10 +25,10 @@ struct00 global_function_1 () { ...@@ -25,10 +25,10 @@ struct00 global_function_1 () {
struct struct0 { struct struct0 {
int struct0_member_function_0 () { int struct0_member_function_0 () {
} // ERROR - XFAIL } // ERROR -
struct0 struct0_member_function_1 () { struct0 struct0_member_function_1 () {
} // ERROR - XFAIL } // ERROR -
}; };
struct struct1 { struct struct1 {
......
...@@ -13,8 +13,8 @@ public: ...@@ -13,8 +13,8 @@ public:
void operator -= (const Char ); void operator -= (const Char );
}; };
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) {} inline char operator == (const Char a, const char b) { return 0; }
char mystrcmp(Char s[31], Char t[31]) char mystrcmp(Char s[31], Char t[31])
{ {
......
...@@ -7,6 +7,6 @@ ...@@ -7,6 +7,6 @@
// Subject: 4 bugs in g++ 2.3.3 // Subject: 4 bugs in g++ 2.3.3
// Message-ID: <9304291053.AA00090@mencon> // Message-ID: <9304291053.AA00090@mencon>
struct A { struct A {
A& operator = (const A& a) {}// ERROR - XFAIL A& operator = (const A& a) {}// WARNING -
}; };
...@@ -7,7 +7,7 @@ void my_unexpected() { ...@@ -7,7 +7,7 @@ void my_unexpected() {
throw 42; throw 42;
} }
template <class T> int foo(T) throw (int) { throw "Hi"; } template <class T> void foo(T) throw (int) { throw "Hi"; }
main() { main() {
std::set_unexpected (my_unexpected); std::set_unexpected (my_unexpected);
......
...@@ -7,7 +7,7 @@ void my_unexpected() { ...@@ -7,7 +7,7 @@ void my_unexpected() {
throw 42; throw 42;
} }
template <class T> int foo(T) throw (T) { throw "Hi"; } template <class T> void foo(T) throw (T) { throw "Hi"; }
main() { main() {
std::set_unexpected (my_unexpected); std::set_unexpected (my_unexpected);
......
...@@ -8,4 +8,5 @@ struct X ...@@ -8,4 +8,5 @@ struct X
void (X::* fee ())() void (X::* fee ())()
{ {
lab: goto lab; lab: goto lab;
return 0;
} }
#include <stddef.h> #include <stddef.h>
extern "C" void abort(); #include <stdlib.h>
class toto { class toto {
public: public:
......
...@@ -12,8 +12,7 @@ struct myint { ...@@ -12,8 +12,7 @@ struct myint {
} }
myint(const myint& mi) { myint(const myint& mi) {
} }
myint& operator=(const myint& mi) { myint& operator=(const myint& mi) { return *this; }
}
}; };
extern pair<const myint, myint> a; extern pair<const myint, myint> a;
......
...@@ -8,7 +8,7 @@ public: ...@@ -8,7 +8,7 @@ public:
class C { class C {
public: public:
bool f (S::E()) { } bool f (S::E()) { return true; }
virtual void foo(); virtual void foo();
}; };
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
class Foo { class Foo {
public: public:
int f(){} int f(){ return 0; }
}; };
void foo() { void foo() {
......
...@@ -23,6 +23,7 @@ struct A { ...@@ -23,6 +23,7 @@ struct A {
if (match_arg != &o) if (match_arg != &o)
fail = 1; fail = 1;
match_arg = &o; match_arg = &o;
return *this;
} }
}; };
......
...@@ -9,7 +9,7 @@ public: ...@@ -9,7 +9,7 @@ public:
X::x() X::x()
{ // ERROR - { // ERROR -
} } // WARNING - no return
X::~x() X::~x()
{ // ERROR - { // ERROR -
......
...@@ -7,6 +7,7 @@ struct S { ...@@ -7,6 +7,7 @@ struct S {
int operator()(int) int operator()(int)
{ {
i = 1; i = 1;
return i;
} }
typedef int I; typedef int I;
...@@ -24,6 +25,7 @@ struct T { ...@@ -24,6 +25,7 @@ struct T {
int operator()(int) int operator()(int)
{ {
j = 1; j = 1;
return j;
} }
void f() { void f() {
......
...@@ -11,7 +11,7 @@ struct S ...@@ -11,7 +11,7 @@ struct S
struct T struct T
{ {
static int f() {} static int f() { return 0; }
}; };
static const S s = { &T::f }; static const S s = { &T::f };
......
// Build don't link: // Build don't link:
typedef __SIZE_TYPE__ size_t; #include <new>
inline void * inline void *
operator new(size_t alloc_sz, const char *fname, unsigned lineno) operator new(size_t alloc_sz, const char *fname, unsigned lineno)
{ {
return ::operator new (alloc_sz);
} }
inline void * inline void *
operator new[](size_t alloc_sz, const char *fname, unsigned lineno) operator new[](size_t alloc_sz, const char *fname, unsigned lineno)
{ {
return ::operator new[] (alloc_sz);
} }
inline void inline void
operator delete(void *ptr, const char *fname, unsigned lineno) operator delete(void *ptr, const char *fname, unsigned lineno)
......
...@@ -6,5 +6,6 @@ struct S { ...@@ -6,5 +6,6 @@ struct S {
virtual int f() { virtual int f() {
new S[+f()]; new S[+f()];
return 0;
} }
}; };
...@@ -39,15 +39,15 @@ class XX { ...@@ -39,15 +39,15 @@ class XX {
public: public:
int xxi; int xxi;
float xxf; float xxf;
int xxf1 () {}; int xxf1 () { return 0; };
int xxf2 (int k) {}; int xxf2 (int k) { return 0; };
}; };
class YY { class YY {
public: public:
int yyi; int yyi;
double yyd; double yyd;
int yyf1 (float f) {}; int yyf1 (float f) { return 0; };
double yyf2 () {return yyd;}; double yyf2 () {return yyd;};
}; };
......
...@@ -13,7 +13,7 @@ public: ...@@ -13,7 +13,7 @@ public:
}; };
struct Operation { struct Operation {
double eval(double) {} double eval(double) { return 0; }
}; };
int main() { int main() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment