Bug 14644 - enum of value zero not converted to (null) pointer
Summary: enum of value zero not converted to (null) pointer
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3.1
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2004-03-19 04:17 UTC by llewins
Modified: 2006-03-31 02:28 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.0.0 2.95.3 3.2.3 3.0.4
Last reconfirmed: 2005-06-09 13:00:49


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description llewins 2004-03-19 04:17:29 UTC
The following code should compile since NULL is a constant expression which 
evaluates to zero. NULL is also an rvalue -- so the questioned reasoning under 
bug 13867 cannot be used.

# 1 "test2.cc"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "test2.cc"
enum {NULL = 0};

void f(int*);

int main()
{
  f(NULL);
}

Instead the following error message is generated:

test2.cc: In function `int main()':
test2.cc:7: error: cannot convert `<anonymous enum>' to `int*' for argument `1'
   to `void f(int*)'

Compiler used is:

~>g++ -v
Reading specs from /usr/lib/gcc-lib/i686-pc-cygwin/3.3.1/specs
Configured with: /GCC/gcc-3.3.1-3/configure --with-gcc --with-gnu-ld --with-
gnu-as --prefix=/usr --exec-prefix=/usr --sysconfdir=/
etc --libdir=/usr/lib --libexecdir=/usr/sbin --mandir=/usr/share/man --
infodir=/usr/share/info --enable-languages=c,ada,c++,f77,pa
scal,java,objc --enable-libgcj --enable-threads=posix --with-system-zlib --
enable-nls --without-included-gettext --enable-interpre
ter --enable-sjlj-exceptions --disable-version-specific-runtime-libs --enable-
shared --disable-win32-registry --enable-java-gc=boe
hm --disable-hash-synchronization --verbose --target=i686-pc-cygwin --
host=i686-pc-cygwin --build=i686-pc-cygwin
Thread model: posix
gcc version 3.3.1 (cygming special)
Comment 1 Andrew Pinski 2004-04-27 19:17:22 UTC
Confirmed.
Comment 2 roger 2006-03-28 21:46:22 UTC
I believe that this may not be a g++ bug.  The wording of the standard is:
[conv.ptr] An null pointer constant is an *integral* constant expression
(_expr.const_) rvalue of integer type that evaluates to zero.
Ignoring the term "rvalue" which was the cause of the misinterpretation
of PR13867, the important aspect is the explicit use of "integral".

Both [expr.const] and [basic.fundamental] distinguish between integral and enumeration constants.  Hence, given the definition "enum { NULL = 0 };",
I believe that "NULL" is an "enumeral constant expression", and that
"(int)NULL" is "integral constant expression".  Note that enumerators may
appear in "integral constant expressions", but are not themselves "integral
constant expressions".

See footnote 20) in section [basic.fundamental] that reiterates:
20) Therefore, enumerations (_dcl.enum_) are  not  integral;  however,
enumerations  can  be promoted to int, unsigned int, long, or unsigned
long, as specified in _conv.prom_.

Note that a standard conversion can contain at most one conversion from
the set "integral promotions" [conv.prom] and "pointer conversions"
[conv.ptr].  i.e. you can't get from enumerator to a pointer in a
single "standard conversion sequence", by my reading of the wording.

Hence in your testcase foo(NULL) is probably invalid, but foo((int)NULL)
should be fine.  Notice if that foo is overloaded, i.e. foo(int) and
foo(int*), there is no ambiguity with using foo(NULL).
 
Although this could perhaps be supported as a GNU extension in
cp/call.c:standard_conversion, if there are other compilers that support
this, the fact that there's a simple fix to make the source code standard
conforming, means that such a patch would unlikely be accepted.

Of course, this may be poor wording in the standard.  I notice that
Stroustrup originally used the wording "A constant expression that
evaluates to 0 ...", and again states that "a constant expression
evaluates to an integral or enumeration constant.".  So this looks like
something standardization tightened up.
Comment 3 Andreas Schwab 2006-03-28 23:01:12 UTC
But [expr.const] also says:

An integral constant-expression can involve only literals (2.13), enumerators, ...

Thus enumerators are also integral constant expressions.  The distinction between integral and enumeration is only at the type level, not as an expression.
Comment 4 Andreas Schwab 2006-03-28 23:09:47 UTC
Ignore my last comment.  The type matters, and what is needed is indeed a constant of _integer_ type, but enumerators are not of integer type.
Comment 5 Mark Mitchell 2006-03-31 02:28:47 UTC
As Roger says, this not a bug.  Roger's analysis is spot on.  (For reference, EDG also rejects this program.)