Following code produces symbol already defined assembler error when compiled with g++ 4.2.4 with -O0 flag. It can compile without problem with g++ 4.1.1. === foo.hpp === class foo { public: template <typename T> operator T (); }; template <typename T> inline foo::operator T () { return (T)0; } === foo.cpp === #include "foo.hpp" struct bar { unsigned int _bar : 24; }; int main() { foo a; unsigned int b = a; bar c; c._bar = a; return 1; } ==== compile with g++ -O0 foo.cpp Regards, Jeng-Liang
Confirmed, a regression from GCC 4.1.1. Here is a self contained example :): class foo { public: template <typename T> operator T (); }; template <typename T> inline foo::operator T () { return (T)0; } struct bar { unsigned int _bar : 24; }; int main() { foo a; unsigned int b = a; bar c; c._bar = a; return 1; }
The following also fails the same way with optimization: class foo { public: template <typename T> __attribute__((noinline)) operator T () { return (T)0; } }; struct bar { unsigned int _bar : 24; }; int main() { foo a; unsigned int b = a; bar c; c._bar = a; return 0; } we instantiate the operator for unsigned int and unsigned int : 24 what we probably should do is treat c._bar = a; as c._bar = (unsigned int : 24)(unsigned int)a; instead.
And for: struct A { template <typename T> __attribute__((noinline)) operator T () { return (T) 0; } }; struct B { unsigned int b : 8; }; int main () { A u; unsigned int v = u; B w; w.b = u; } we instantiate both A::operator unsigned int<unsigned int>() A::operator unsigned char<unsigned char>() Shouldn't it use unsigned int conversion in both cases as well, or is it allowed (or required) to use the lowered type? I see 3.4 through 4.4 all use unsigned char, if RHS' type isn't MAYBE_CLASS_TYPE_P, then I understand it, but for class RHS it is an important difference. I believe the place which needs to be revisited is cp_build_modify_expr, if is_bitfield_expr_with_lowered_type use the type returned by that in convert_for_assignment. But I'm e.g. confused by: /* If storing into a structure or union member, it has probably been given type `int'. Compute the type that would go with the actual amount of storage the member occupies. */ if (TREE_CODE (lhs) == COMPONENT_REF && (TREE_CODE (lhstype) == INTEGER_TYPE || TREE_CODE (lhstype) == REAL_TYPE || TREE_CODE (lhstype) == ENUMERAL_TYPE)) { lhstype = TREE_TYPE (get_unwidened (lhs, 0)); ... } That seems like a remnant from the past, as get_unwidened for COMPONENT_REF does nothing but return the passed object. See http://gcc.gnu.org/ml/gcc-patches/2008-03/msg01621.html
Subject: Bug 38007 Author: jason Date: Wed Nov 12 20:50:45 2008 New Revision: 141800 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141800 Log: PR c++/38007 gcc/cp/ * typeck.c (cp_build_modify_expr): Update bitfield handling. gcc/ * c-common.c (c_common_signed_or_unsigned_type): Remove C++ special casing. gcc/testsuite/ * g++.dg/conversion/bitfield10.C: New test. * g++.dg/warn/pr35635.C (func1): Accept additional warning. * g++.old-deja/g++.mike/enum1.C: Expect warn about assignment. * g++.dg/expr/bitfield9.C: Pass -Wno-overflow. Added: trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C Modified: trunk/gcc/ChangeLog trunk/gcc/c-common.c trunk/gcc/cp/ChangeLog trunk/gcc/cp/typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/g++.dg/expr/bitfield9.C trunk/gcc/testsuite/g++.dg/warn/pr35635.C trunk/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
Subject: Bug 38007 Author: jason Date: Wed Nov 12 22:08:01 2008 New Revision: 141808 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141808 Log: PR c++/38007 gcc/cp/ * typeck.c (cp_build_modify_expr): Update bitfield handling. gcc/ * c-common.c (c_common_signed_or_unsigned_type): Remove C++ special casing. gcc/testsuite/ * g++.dg/conversion/bitfield10.C: New test. * g++.dg/warn/pr35635.C (func1): Accept additional warning. * g++.old-deja/g++.mike/enum1.C: Expect warn about assignment. * g++.dg/expr/bitfield9.C: Pass -Wno-overflow. Added: branches/gcc-4_3-branch/gcc/testsuite/g++.dg/conversion/bitfield10.C - copied unchanged from r141800, trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C Modified: branches/gcc-4_3-branch/gcc/ChangeLog branches/gcc-4_3-branch/gcc/c-common.c branches/gcc-4_3-branch/gcc/cp/ChangeLog branches/gcc-4_3-branch/gcc/cp/typeck.c branches/gcc-4_3-branch/gcc/testsuite/ChangeLog branches/gcc-4_3-branch/gcc/testsuite/g++.dg/expr/bitfield9.C branches/gcc-4_3-branch/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
Subject: Bug 38007 Author: jason Date: Wed Nov 12 22:13:26 2008 New Revision: 141809 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141809 Log: PR c++/38007 gcc/cp/ * typeck.c (cp_build_modify_expr): Update bitfield handling. gcc/ * c-common.c (c_common_signed_or_unsigned_type): Remove C++ special casing. gcc/testsuite/ * g++.dg/conversion/bitfield10.C: New test. * g++.dg/warn/pr35635.C (func1): Accept additional warning. * g++.old-deja/g++.mike/enum1.C: Expect warn about assignment. * g++.dg/expr/bitfield9.C: Pass -Wno-overflow. Added: branches/gcc-4_2-branch/gcc/testsuite/g++.dg/conversion/bitfield10.C - copied unchanged from r141800, trunk/gcc/testsuite/g++.dg/conversion/bitfield10.C Modified: branches/gcc-4_2-branch/gcc/ChangeLog branches/gcc-4_2-branch/gcc/c-common.c branches/gcc-4_2-branch/gcc/cp/ChangeLog branches/gcc-4_2-branch/gcc/cp/typeck.c branches/gcc-4_2-branch/gcc/testsuite/ChangeLog branches/gcc-4_2-branch/gcc/testsuite/g++.dg/expr/bitfield9.C branches/gcc-4_2-branch/gcc/testsuite/g++.old-deja/g++.mike/enum1.C
Fixed on all open branches.