Bug 28236 - wrong "control reaches" warning with enums.
Summary: wrong "control reaches" warning with enums.
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.2
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL: http://gcc.gnu.org/ml/gcc/2007-01/msg...
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2006-07-03 16:53 UTC by Pawel Sikora
Modified: 2007-01-29 11:09 UTC (History)
2 users (show)

See Also:
Host: x86-64-linux
Target: x86-64-linux
Build: x86-64-linux
Known to work:
Known to fail: 3.3.6 4.1.2 4.2.0
Last reconfirmed: 2006-07-06 16:55:34


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Pawel Sikora 2006-07-03 16:53:19 UTC
typedef enum { foo, bar } e;
int zoo( e __e )
{
        switch ( __e )
        {
                case foo: return -1;
                case bar: return +1;
        }
}

bug.cpp: In function 'int zoo(e)':
bug.cpp:9: warning: control reaches end of non-void function
Comment 1 Pawel Sikora 2006-07-03 17:00:13 UTC
zoo (__e)
{
  int D.1616;
<bb 0>:
  switch (__e)
    {
      case 0: goto <L0>;
      case 1: goto <L5>;
      default : goto <L2>;  <====
    }
<L0>:;
  D.1616 = -1;
  goto <bb 3> (<L3>);
<L2>:;
  return;                   <==== problem.
<L5>:;
  D.1616 = 1;
<L3>:;
  return D.1616;
}
Comment 2 Andrew Pinski 2006-07-06 16:55:34 UTC
Values in enums that are out of range are undefined in C++ (while defined in C).
Comment 3 Pawel Sikora 2006-07-31 14:35:35 UTC
one more testcase that renders different warning.

typedef enum { X, Y } e;
e zoo( e __e )
{
        e r;
        switch ( __e )
        {
                case X: r = Y; break;
                case Y: r = X; break;
        }
        return r;
}

bug.cpp: In function 'e zoo(e)':
bug.cpp:4: warning: 'r' may be used uninitialized in this function

e zoo(e) (__e)
{
  e r;
  e D.2076;
  int __e.0;
<bb 0>:
  switch ((int) __e)
    {
      case 0: goto <L0>;
      case 1: goto <L6>;
      default : goto <L5>;
    }
<L6>:;
  r = 0;
  goto <bb 3> (<L2>);
<L5>:;
  goto <bb 3> (<L2>);
<L0>:;
  r = 1;
<L2>:;
  return r;
}
Comment 4 Pawel Sikora 2006-07-31 14:41:58 UTC
so, -Werror is useless now.
Comment 5 Manuel López-Ibáñez 2007-01-23 13:57:04 UTC
I don't get this. The enum value can be any integer apart from foo and bar.  Moreover, since it is undefined, it can be literally anything! So you need a "default:" case to handle that. 

In the first testcase, without a default case, the function returns (when it reaches the end) without a value, so the warning is correct.

In the second case, r is not initialized unless __e is X or Y (and if out-of-range enum values are undefined in C++, __e can be anything!), thus the warning seems correct as well.

So, is this really a bug?

Comment 6 Pawel Sikora 2007-01-23 15:02:24 UTC
(In reply to comment #5)
> I don't get this. The enum value can be any integer apart from foo and bar.

3.9.1/7, subnote. 43) says that enum isn't an integral type
but can be promoted to {signed/unsigned} int/long.

an assignment of int to enum produces an error,
so how ( in defined non-hax0r way ) enum can be any integer?
if it can be, then what's difference between enum and int?


$ cat tmp.cpp
typedef enum { foo, bar } e;
e assign( int v__ )  { return v__; }
int promote( e e__ ) { return e__; }

$ x86_64-gnu-linux-g++ tmp.cpp -O2 -c -Wall
tmp.cpp: In function 'e assign(int)':
tmp.cpp:2: error: invalid conversion from 'int' to 'e'
Comment 7 Manuel López-Ibáñez 2007-01-23 15:55:56 UTC
(In reply to comment #6)
> 
> an assignment of int to enum produces an error,
> so how ( in defined non-hax0r way ) enum can be any integer?
> if it can be, then what's difference between enum and int?

Undefined behaviour exists. It can happen. It will happen. Is casting a "hax0r way"? 

manu@localhost:~$ cat test.cc
#include <stdio.h>

typedef enum { foo, bar } e;
int zoo( e __e )
{
        switch ( __e )
        {
                case foo: return -1;
                case bar: return +1;
        }
}

int main()
{
  printf("%d\n", zoo((e)10));
  return 0;
}
manu@localhost:~$ g++ -pedantic test.cc -o test
manu@localhost:~$ ./test
-1209364588


We have requests for warnings about out-of-range enum conversions in C++:

* PR 12242
* PR 27975
* PR 12242

Again, I am just trying to understand the issue here. You will get a more expert opinion about the standard and whether this is an actual bug or you should have a default: case in your switch statements in the gcc@gcc.gnu.org mailing list.
Comment 8 Manuel López-Ibáñez 2007-01-23 15:57:40 UTC
(In reply to comment #7)
> 
> * PR 12242
> * PR 27975
> * PR 12242

This should have been:

* PR 12242
* PR 27975
* PR 30357
Comment 9 Manuel López-Ibáñez 2007-01-29 01:10:50 UTC
Pawel, I don't want to appear rude but as you see from the answers in the ML, control might reach the end of the function without an explicit return. Thus, the warning is valid and I think we should close this as INVALID. Don't you agree?
Comment 10 Manuel López-Ibáñez 2007-01-29 11:09:33 UTC
WONTFIX as decided here:

http://gcc.gnu.org/ml/gcc/2007-01/msg01179.html