Try to compile the following tiny sample code with gcc 3.4.0: ----------------------------------------------------------------------- class S { }; class X { public: void * v; S s; X(void * v_, const S & s_) : v(v_), s(s_) { } }; template <class T> class Y : public T { public: template <typename X1, typename X2> Y(X1 & x1, X2 & x2) : T(x1, x2) { } }; void test(void) { S s; void * v = &s; Y<X> * y1 = new Y<X>(v, s); // works Y<X> * y3 = new Y<X>(reinterpret_cast<void *>(v), s); // works Y<X> * y2 = new Y<X>((void *)v, s); // error - but why?? } ----------------------------------------------------------------------- Only one of the three lines with "... = new Y<X>..." triggers an error, though that and also the error message as such does not seem plausible: templ_constr.cxx: In function `void test()': templ_constr.cxx:30: error: no matching function for call to `Y<X>::Y(void*, S&)' templ_constr.cxx:15: note: candidates are: Y<X>::Y(const Y<X>&) templ_constr.cxx:18: note: Y<T>::Y(X1&, X2&) [with X1 = void*, X2 = S, T = X] Any idea what this error is about?
Just noticed that the sample code can be made even simpler, the second class isn't necessary: ------------------------------------------------------------------------------- class X { public: void * v; X(void * v_) : v(v_) { } }; template <class T> class Y : public T { public: template <typename X1> Y(X1 & x1) : T(x1) { } }; void test(void) { void * v = (void *)123; Y<X> * y1 = new Y<X>(v); // works Y<X> * y3 = new Y<X>(reinterpret_cast<void *>(v)); // works Y<X> * y2 = new Y<X>((void *)v); // error - why?? } ------------------------------------------------------------------------------
I think that both using reinterpret_cast and the old style cast should be rejected here because you are binding an rvalue to an lvalue (a non constant one) through a cast which should be rejected. The error occurs because of the removal of the casts are lvalue extension in 3.4.0.
Indeed, your code should not be accepted, since you can't bind an rvalue to a non-const reference (this is something that gcc supported as an extension in the past, but it was deemed Evil). Here's something smaller: ----------------- struct Y { Y(int &); }; int v; Y y1(reinterpret_cast<int>(v)); Y y2((int)v); ---------------- gcc3.4 only rejects the second line, though I believe it should also do so for the first one (like icc does): g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ -c x.cc x.cc:5: error: no matching function for call to `Y::Y(int)' x.cc:1: note: candidates are: Y::Y(const Y&) x.cc:1: note: Y::Y(int&) g/x> icc -c -Xc -ansi x.cc x.cc(4): error: no instance of constructor "Y::Y" matches the argument list argument types are: (int) Y y1(reinterpret_cast<int>(v)); ^ x.cc(5): error: no instance of constructor "Y::Y" matches the argument list argument types are: (int) Y y2((int)v); ^ compilation aborted for x.cc (code 2) BTW, gcc2.95 had this error message, which is somewhat clearer: g/x> /home/bangerth/bin/gcc-2.95.3/bin/c++ -c x.cc x.cc: In function `void __static_initialization_and_destruction_0(int, int)': x.cc:4: initialization of non-const reference type `int &' x.cc:4: from rvalue of type `int' x.cc:1: in passing argument 1 of `Y::Y(int &)' x.cc:5: initialization of non-const reference type `int &' x.cc:5: from rvalue of type `int' x.cc:1: in passing argument 1 of `Y::Y(int &)' (This error message regression is tracked somewhere else, though.) However, note that 2.95 rejected both calls, as does 3.2.3. That we accept the first one is a regression introduced in 3.3: g/x> /home/bangerth/bin/gcc-3.2.3/bin/c++ -c x.cc x.cc: In function `void __static_initialization_and_destruction_0(int, int)': x.cc:4: no matching function for call to `Y::Y(int)' x.cc:1: candidates are: Y::Y(const Y&) x.cc:1: Y::Y(int&) x.cc:5: no matching function for call to `Y::Y(int)' x.cc:1: candidates are: Y::Y(const Y&) x.cc:1: Y::Y(int&) g/x> g/x> g/x> /home/bangerth/bin/gcc-3.3*/bin/c++ -c x.cc x.cc:5: error: no matching function for call to `Y::Y(int)' x.cc:1: error: candidates are: Y::Y(const Y&) x.cc:1: error: Y::Y(int&) W.
Most likely what is happening is that the old style class is returning a non-lvalue tree type (either a NOP or a NON_LVALUE) but the reinterpret_cast is not doing that.
Retargeting to 3.4.1, being a regression on that release branch.
Working on a fix.
Subject: Bug 15076 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2004-06-10 14:26:23 Modified files: gcc/cp : ChangeLog parser.c pt.c typeck.c Added files: gcc/testsuite/g++.dg/conversion: const1.C reinterpret1.C gcc/testsuite/g++.dg/template: enum2.C error13.C Log message: PR c++/15227 * parser.c (cp_parser_direct_declarator): Robustify. PR c++/15877 * pt.c (tsubst_copy): Use decl_constant_value on enumeration constants in non-dependent contexts. PR c++/14211 PR c++/15076 * typeck.c (build_static_cast): Wrap casts in NON_LVALUE_EXPR when necessary. PR c++/14211 * g++.dg/conversion/const1.C: New test. PR c++/15076 * g++.dg/conversion/reinterpret1.C: New test. PR c++/15877 * g++.dg/template/enum2.C: New test. PR c++/15227 * g++.dg/template/error13.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4089&r2=1.4090 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&r1=1.202&r2=1.203 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&r1=1.860&r2=1.861 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&r1=1.548&r2=1.549 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/conversion/const1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/conversion/reinterpret1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/enum2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/error13.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 15076 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-06-10 14:26:50 Modified files: gcc/cp : ChangeLog parser.c pt.c typeck.c Added files: gcc/testsuite/g++.dg/conversion: const1.C reinterpret1.C gcc/testsuite/g++.dg/template: enum2.C error13.C Log message: PR c++/15227 * parser.c (cp_parser_direct_declarator): Robustify. PR c++/15877 * pt.c (tsubst_copy): Use decl_constant_value on enumeration constants in non-dependent contexts. PR c++/14211 PR c++/15076 * typeck.c (build_static_cast): Wrap casts in NON_LVALUE_EXPR when necessary. PR c++/14211 * g++.dg/conversion/const1.C: New test. PR c++/15076 * g++.dg/conversion/reinterpret1.C: New test. PR c++/15877 * g++.dg/template/enum2.C: New test. PR c++/15227 * g++.dg/template/error13.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.119&r2=1.3892.2.120 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/parser.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.157.2.32&r2=1.157.2.33 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/pt.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.816.2.29&r2=1.816.2.30 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.519.2.19&r2=1.519.2.20 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/conversion/const1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/conversion/reinterpret1.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/enum2.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/error13.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1
*** This bug has been marked as a duplicate of 14211 ***