Bug 20624 - [4.0 Regression] wrong "control reaches end of non-void function" warning
Summary: [4.0 Regression] wrong "control reaches end of non-void function" warning
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.2
Assignee: Andrew Pinski
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: diagnostic, patch
: 20918 (view as bug list)
Depends on:
Blocks:
 
Reported: 2005-03-24 16:27 UTC by Oliver Stoeneberg
Modified: 2012-05-24 13:57 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.1.0
Known to fail:
Last reconfirmed: 2005-03-24 18:02:50


Attachments
preprocssed source (64.10 KB, application/octet-stream)
2005-03-24 16:55 UTC, Oliver Stoeneberg
Details
Reduced code from stlport that shows the problem (616 bytes, text/plain)
2005-04-20 09:29 UTC, pmladek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Oliver Stoeneberg 2005-03-24 16:27:39 UTC
If you compile this code 

#include <fstream>

void test()
{
 	 std::ifstream in;
}

against the actual CVS version of STLport 5.0
(http://www.breaken.de/temp/STLport.zip) you get this warning:

  In member function 'typename stlp_std::basic_filebuf<_CharT,
_Traits>::pos_type stlp_std::basic_filebuf<_CharT, _Traits>::seekoff(typename
_Traits::off_type, int, int) [with _CharT = char, _Traits =
stlp_std::char_traits<char>]': 
372 C:\cvs\STLport\stlport\stl\_fstream.c [Warning] control reaches end of
non-void function 

Because the STLport is very complex I wasn't able to reduce the code properly.
Maybe it can already be done by just posting the function causing it:

template <class _CharT, class _Traits>
__BF_pos_type__
basic_filebuf<_CharT, _Traits>::seekoff(off_type __off,
                                        ios_base::seekdir __whence,
                                        ios_base::openmode /* dummy */) {
  if (this->is_open() &&
      (__off == 0 || (_M_constant_width && this->_M_base._M_in_binary_mode()))) {

    if (!_M_seek_init(__off != 0 || __whence != ios_base::cur))
      return pos_type(-1);

    // Seek to beginning or end, regardless of whether we're in input mode.
    if (__whence == ios_base::beg || __whence == ios_base::end)
      return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
                            _State_type());

    // Seek relative to current position.  Complicated if we're in input mode.
    else if (__whence == ios_base::cur) {

      if (!_M_in_input_mode)
        return _M_seek_return(_M_base._M_seek(_M_width * __off, __whence),
                              _State_type());
      else if (_M_mmap_base != 0) {
        // __off is relative to gptr().  We need to do a bit of arithmetic
        // to get an offset relative to the external file pointer.
        streamoff __adjust = _M_mmap_len - (this->gptr() - (_CharT*) _M_mmap_base);

        // if __off == 0, we do not need to exit input mode and to shift file
pointer
        if (__off == 0) {
          return pos_type(_M_base._M_seek(0, ios_base::cur) - __adjust);
        }
        else
          return _M_seek_return(_M_base._M_seek(__off - __adjust,
ios_base::cur), _State_type());
      }
      else if (_M_constant_width) { // Get or set the position.  

        streamoff __iadj = _M_width * (this->gptr() - this->eback());
        
        // Compensate for offset relative to gptr versus offset relative
        // to external pointer.  For a text-oriented stream, where the 
        // compensation is more than just pointer arithmetic, we may get
        // but not set the current position.
        
        if (__iadj <= _M_ext_buf_end - _M_ext_buf) {
          
          streamoff __eadj =  _M_base._M_get_offset(_M_ext_buf + __iadj,
_M_ext_buf_end);

          if (__off == 0) {
            return pos_type(_M_base._M_seek(0, ios_base::cur) - __eadj);
          }  else {
            return _M_seek_return(_M_base._M_seek(__off - __eadj,
ios_base::cur), _State_type());
          }
        }
        else
          return pos_type(-1);
      }
      else {                    // Get the position.  Encoding is var width.
        // Get position in internal buffer.
        ptrdiff_t __ipos = this->gptr() - this->eback();
        
        // Get corresponding position in external buffer.
        _State_type __state = _M_state;
        int __epos = _M_codecvt->length(__state, _M_ext_buf, _M_ext_buf_end,
                                        __ipos);

        // Sanity check (expensive): make sure __epos is the right answer.
        _State_type __tmp_state = _M_state;
        _Filebuf_Tmp_Buf<_CharT> __buf(__ipos);
        _CharT* __ibegin = __buf._M_ptr;
        _CharT* __inext  = __ibegin;

        const char* __dummy;
        typename _Codecvt::result __status
          = _M_codecvt->in(__tmp_state,
                           _M_ext_buf, _M_ext_buf + __epos, __dummy,
                           __ibegin, __ibegin + __ipos, __inext);
        if (__status != _Codecvt::error &&
            (__status == _Codecvt::noconv ||
             (__inext == __ibegin + __ipos &&
              equal(this->gptr(), this->eback(), __ibegin,
                    _Eq_traits<traits_type>())))) {
          // Get the current position (at the end of the external buffer),
          // then adjust it.  Again, it might be a text-oriented stream.
          streamoff __cur = _M_base._M_seek(0, ios_base::cur);
          streamoff __adj =
            _M_base._M_get_offset(_M_ext_buf, _M_ext_buf + __epos) -
            _M_base._M_get_offset(_M_ext_buf, _M_ext_buf_end);
          if (__cur != -1 && __cur + __adj >= 0)
            return _M_seek_return(__cur + __adj, __state);
          else
            return pos_type(-1);
        }
        else                    // We failed the sanity check.
          return pos_type(-1);
      }
    }
    else                        // Unrecognized value for __whence.
      return pos_type(-1);
  }
  else
    return pos_type(-1);
}

I also got another piece of code, that also causes a wrong warning, but I wasn't
able to reduce that code either.

I am using

Target: i686-pc-mingw32
Configured with: /datal/gcc/gcc/configure --prefix=/datal/gcc/build/wingcc
--build=i686-pc-linux-gnu --host=i686-pc-mingw32 --target=i686-pc-mingw32
--enable-languages=c,c++,java --with-gcc --with-gnu-as --with-gnu-ld
--enable-threads=win32 --disable-nls --disable-win32-registry --disable-shared
--disable-debug --without-newlib --enable-libgcj --disable-java-awt --without-x
--enable-java-gc=boehm --disable-libgcj-debug --enable-interpreter
--enable-hash-synchronization --enable-sjlj-exceptions --enable-libgcj-multifile
--enable-libgcj-mingw-osapi=ansi
Thread model: win32
gcc version 4.0.0 20050320 (prerelease)
Comment 1 Andrew Pinski 2005-03-24 16:30:09 UTC
(In reply to comment #0)
> If you compile this code 
> > against the actual CVS version of STLport 5.0

Two things, Please attach the preprocessed source.

Second why are you using STLport instead of the GCC's libstdc++?
Comment 2 Oliver Stoeneberg 2005-03-24 16:54:31 UTC
> Second why are you using STLport instead of the GCC's libstdc++?

Because we had problems with the default GCC STL in the past, so we switched to
STLport. We are also working cross-platform (GCC for linux and MSVC6 for win32)
and having the same STL in both versions gives you the security, that the
behavior is the same (well...kind of...at least the behavior should be closer
than STLs from two different vendors)

Comment 3 Oliver Stoeneberg 2005-03-24 16:55:19 UTC
Created attachment 8451 [details]
preprocssed source
Comment 4 Andrew Pinski 2005-03-24 17:09:57 UTC
(In reply to comment #2)
> > Second why are you using STLport instead of the GCC's libstdc++?
> 
> Because we had problems with the default GCC STL in the past, so we switched to
> STLport. We are also working cross-platform (GCC for linux and MSVC6 for win32)
> and having the same STL in both versions gives you the security, that the
> behavior is the same (well...kind of...at least the behavior should be closer
> than STLs from two different vendors)

Well considering STL is standardized now and has been since 1998 I really doubt there is any problem 
any more and if there is a different behavor, it might be undefined by the standard or a bug in one of 
the STL implemenation.  But anyways I will look into reducing the preprocessed source.
Comment 5 Andrew Pinski 2005-03-24 17:18:11 UTC
What option are you using as I cannot reproduce with any option I tried.
Comment 6 Oliver Stoeneberg 2005-03-24 17:32:08 UTC
I know, that there is a standard, but it's only a standard and any
implementation can have its own bugs. And having just one STL you should run
into the same bugs and not having it working fine on one operating system and
not running on another one and to find out, that one of them has an obscure and
very deep bug in it, after days of debugging. That's why we switched.
And even STLport wasn't(isn't) really standard compliant yet, because some
functions returned somethign they shouldn't return. 
MSVC, GCC, BCB, ICC are also all behaving different although they have a
standard to apply to...and I also still see a lot of open GCC bug reports about
accepting invalid or rejecting valid code ;-)

I am using the following options:

-Wextra -Wall -Wshadow -Wwrite-strings -Wdisabled-optimization -Wno-long-long
-Wno-unknown-pragmas -Wsign-compare  -Wpointer-arith -Winline -Wno-reorder
-Wno-missing-braces -save-temps -fexceptions -fmessage-length=0

But just using -Wall already triggers the warning for me.

You also have to include the "STLport/stlport" folder as the first one, so it
lies on top of the standard includes.
Comment 7 Andrew Pinski 2005-03-24 18:02:50 UTC
Ok, now I can confirm it.  The problem was I was using optimization.
Anyways the short testcase:
struct s {~s(); s();};
int f(int f2, int f3)
{
  s gg;
  if (f3 && f2)
    return 1;
  else
    return 54;
}


: Search converges between 2004-07-09-trunk (#483) and 2004-07-12-trunk (#484).
Comment 8 Oliver Stoeneberg 2005-03-25 02:02:58 UTC
OK, next week I will try to isolate the other occurance of a wrong warning and
file another bug report. Maybe there's another reason for the wrong warning in
that case (not STLport related).
Comment 9 Oliver Stoeneberg 2005-03-29 09:58:36 UTC
I could isolate the other warning and reduce the soce a bit. I filed it as PR
20681. Could be a duplicate.
Comment 10 Mark Mitchell 2005-04-08 21:46:34 UTC
Removing rejects-valid; treating all incorrect warnings as rejects-valid due to
-Werror is not useful.
Comment 11 Andrew Pinski 2005-04-09 17:01:08 UTC
*** Bug 20918 has been marked as a duplicate of this bug. ***
Comment 12 pmladek 2005-04-20 09:29:33 UTC
Created attachment 8687 [details]
Reduced code from stlport that shows the problem

I have reduced the code used by stlport. It is still about 100 lines. I was not
able to reduce it more and keep the warning. But I think that it could be
useful.

Here is output:
$> g++ --version
g++ (GCC) 4.0.0 20050415 (prerelease) (SUSE Linux)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$> g++ -Wall -c return.cxx 
return.cxx: In member function ‘typename basic_filebuf<_CharT, 
_Traits>::pos_type basic_filebuf<_CharT, _Traits>::seekoff(int) [with _CharT 
= char, _Traits = char_traits<char>]’:
return.cxx:77: warning: control reaches end of non-void function

BTW: I am not able to get the warning with the testcase mentioned in the
comment #7.
Comment 13 Andrew Pinski 2005-08-17 15:55:01 UTC
Reduced new testcase:
struct fpos {
 fpos(int __pos) {}
};
struct g {
  g();
  ~g();
};
fpos seekoff(int b, int c)
{
  g __buf;
  if (b != -1 && c >= 0)
    return fpos(-1);
  else
    return fpos(-1);
} 

The issue here is (produced inside the compiler):
        return <retval>;
        goto <D1792>;


Which means this PR 20681 is a dup of this as the problem is the same.
Comment 14 Andrew Pinski 2005-08-17 15:55:55 UTC
*** Bug 20681 has been marked as a duplicate of this bug. ***
Comment 15 Andrew Pinski 2005-08-17 19:30:38 UTC
(In reply to comment #13)
> The issue here is (produced inside the compiler):
>         return <retval>;
>         goto <D1792>;

After removing that goto, we still have an issue with the label for D1792.  I wonder how can we remove 
that lablel.
Comment 16 Steven Bosscher 2005-08-17 21:47:27 UTC
FYI, this is the CFG for the test case of comment #13 at the point where 
the warning is issued: 
 
fpos seekoff(int, int) (b, c) 
{ 
  int finally_tmp.0; 
  struct g __buf; 
  struct fpos D.2120; 
  struct fpos D.2119; 
  struct fpos D.2123; 
 
  # BLOCK 0 
  # PRED: ENTRY (fallthru) 
  __comp_ctor  (&__buf); 
  if (b == -1) goto <L2>; else goto <L0>; 
  # SUCC: 3 (true) 1 (false) 
 
  # BLOCK 1 
  # PRED: 0 (false) 
<L0>:; 
  if (c < 0) goto <L2>; else goto <L1>; 
  # SUCC: 3 (true) 2 (false) 
 
  # BLOCK 2 
  # PRED: 1 (false) 
<L1>:; 
  __comp_ctor  (&D.2119, -1); 
  D.2123 = D.2119; 
  finally_tmp.0 = 0; 
  goto <bb 4> (<L4>); 
  # SUCC: 4 (fallthru) 
 
  # BLOCK 3 
  # PRED: 0 (true) 1 (true) 
<L2>:; 
  __comp_ctor  (&D.2120, -1); 
  D.2123 = D.2120; 
  finally_tmp.0 = 0; 
  # SUCC: 4 (fallthru) 
 
  # BLOCK 4 
  # PRED: 2 (fallthru) 3 (fallthru) 
<L4>:; 
  __comp_dtor  (&__buf); 
  switch (finally_tmp.0) 
    { 
      case 1: goto <L5>; 
      default : goto <L6>; 
    } 
  # SUCC: 5 6 
 
  # BLOCK 5 
  # PRED: 4 
<L5>:; 
  return; 
  # SUCC: EXIT 
 
  # BLOCK 6 
  # PRED: 4 
<L6>:; 
  return D.2123; 
  # SUCC: EXIT 
 
} 
 
Comment 17 Andrew Pinski 2005-08-17 22:34:48 UTC
I have a patch wich fixes this bug but not 20681:
Index: gimple-low.c
===============================================================
====
RCS file: /cvs/gcc/gcc/gcc/gimple-low.c,v
retrieving revision 2.26
diff -u -p -r2.26 gimple-low.c
--- gimple-low.c        30 Jun 2005 00:47:49 -0000      2.26
+++ gimple-low.c        17 Aug 2005 22:34:31 -0000
@@ -368,6 +368,9 @@ block_may_fallthru (tree block)
     case CALL_EXPR:
       /* Functions that do not return do not fall through.  */
       return (call_expr_flags (stmt) & ECF_NORETURN) == 0;
+    
+    case CLEANUP_POINT_EXPR:
+      return block_may_fallthru (TREE_OPERAND (stmt, 0));
 
     default:
       return true;
Comment 18 Andrew Pinski 2005-08-17 22:47:18 UTC
(In reply to comment #7)
> Ok, now I can confirm it.  The problem was I was using optimization.
> Anyways the short testcase:

Oh, I know why this testcase does not fail any more, because I made it double check 
CLEANUP_POINT_EXPR on RETURN_EXPR.
Comment 19 Andrew Pinski 2005-08-18 20:10:51 UTC
Patch posted here: <http://gcc.gnu.org/ml/gcc-patches/2005-08/msg01102.html>
which fixes this issue but not the one in PR 20681 which is a semi front-end bug in that it should have 
not emitted the break to IR.
Comment 20 Andrew Pinski 2005-08-19 05:41:28 UTC
Fixed on the mainline, will apply to the 4.0 branch later today (after class around 12pm EDT).
Comment 21 GCC Commits 2005-08-19 05:41:39 UTC
Subject: Bug 20624

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	pinskia@gcc.gnu.org	2005-08-19 05:41:14

Modified files:
	gcc            : ChangeLog gimple-low.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/warn: Wreturn-3.C 

Log message:
	2005-08-19  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR middle-end/20624
	* g++.dg/warn/Wreturn-3.C: New test
	
	2005-08-19  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR middle-end/20624
	* gimple-low.c (block_may_fallthru): Handle CLEANUP_POINT_EXPR by
	looking past it.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.9776&r2=2.9777
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gimple-low.c.diff?cvsroot=gcc&r1=2.26&r2=2.27
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5936&r2=1.5937
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/warn/Wreturn-3.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 22 GCC Commits 2005-08-20 20:37:19 UTC
Subject: Bug 20624

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-4_0-branch
Changes by:	pinskia@gcc.gnu.org	2005-08-20 20:37:14

Modified files:
	gcc            : ChangeLog gimple-low.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/g++.dg/warn: Wreturn-3.C 

Log message:
	2005-08-20  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR middle-end/20624
	* gimple-low.c (block_may_fallthru): Handle CLEANUP_POINT_EXPR
	by looking past it.
	
	2005-08-20  Andrew Pinski  <pinskia@physics.uc.edu>
	
	PR middle-end/20624
	* g++.dg/warn/Wreturn-3.C: New test

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=2.7592.2.379&r2=2.7592.2.380
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/gimple-low.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=2.22&r2=2.22.8.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.5084.2.340&r2=1.5084.2.341
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/warn/Wreturn-3.C.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=NONE&r2=1.1.2.1

Comment 23 Andrew Pinski 2005-08-20 20:37:30 UTC
Fixed in 4.0.2 and above.
Comment 24 Pawel Sikora 2008-04-16 08:03:49 UTC
(In reply to comment #23)
> Fixed in 4.0.2 and above.
> 

i have one more testcase which still exposes this bug.

$ cat 0.cpp
struct X
{
        X();
        ~X();
};

bool f( int k )
{
        X x;
        switch ( k )
        {
                default:
                        return false;
                        break;
        }
}

$ g++ 0.cpp -Wall -fdump-tree-gimple -g0 -c -o /dev/null
0.cpp: In function &#8216;bool f(int)&#8217;:
0.cpp:16: warning: control reaches end of non-void function

$ cat 0.cpp.004t.gimple
bool f(int) (k)
{
  bool D.2056;
  struct X x;

  __comp_ctor  (&x);
  try
    {
      switch (k)
        {
          default : goto <D.2054>;
        }
      <D.2054>:;
      D.2056 = 0;
      return D.2056;
      goto <D.2055>;
      <D.2055>:;
    }
  finally
    {
      __comp_dtor  (&x);
    }
}
Comment 25 Manuel López-Ibáñez 2008-04-21 13:07:41 UTC
Reopened per new testcase.
Comment 26 Pawel Sikora 2008-04-21 13:15:07 UTC
and one more testcase, similar to c#24:

extern int i, j, k;
struct X { X(); ~X(); };
bool f()
{
  X x;
  if ( i && j )
    if ( k < 0 ) return true; else return false;
  else
    return false;
}

tested on gcc-4.3-svn20080417
Comment 27 Pawel Sikora 2008-04-23 09:24:42 UTC
(In reply to comment #26)

> tested on gcc-4.3-svn20080417
 
fails also on 4.1 and 4.2.
Comment 28 Andrew Pinski 2008-05-17 00:01:51 UTC
(In reply to comment #25)
> Reopened per new testcase.

Please open a new bug for that testcase.
Comment 29 online games 2012-05-24 13:57:55 UTC
http://free-online-games-mmorpg.blogspot.co.uk/