From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 318 invoked by alias); 19 Aug 2013 18:09:17 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 32745 invoked by uid 48); 19 Aug 2013 18:09:16 -0000 From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/58192] G++ emits incorrect code when passing enum classes as function parameters Date: Mon, 19 Aug 2013 18:09:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 4.8.1 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2013-08/txt/msg00964.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=58192 Jakub Jelinek changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org, | |rth at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- The difference is that in the S1::::set(Foo) case setup_incoming_promotions in combine.c says that the argument has non-zero mask of 0xff, because the function is local to the TU, while for S2 all caller's aren't guaranteed local and thus it isn't optimized. The argument type is Foo (QImode) passed in SImode register, guess combine.c expects that caller zero-extends in this case, but it doesn't (in neither case). enum class Foo : unsigned char { FOO }; struct S1 { struct { unsigned int i; void __attribute__((noinline)) set (Foo foo) { i = static_cast (foo); } } x; }; struct S2 { struct X { unsigned int i; void __attribute__((noinline)) set (Foo foo) { i = static_cast (foo); } }; X x; }; struct T { unsigned short i; Foo f; unsigned char c; }; __attribute__((noinline)) void baz (unsigned int x) { if (x != 0) __builtin_abort (); } void bar (T t) { S1 s1; s1.x.set(t.f); baz (s1.x.i); S2 s2; s2.x.set(t.f); baz (s2.x.i); } int main() { T t = { 0xabcd, Foo::FOO, 0xef}; bar (t); } For: unsigned int v1, v2; __attribute__((noinline, noclone)) static void foo (unsigned char a) { v1 = a; } __attribute__((noinline, noclone)) void bar (unsigned char a) { v2 = a; } void baz (unsigned int a) { foo (a); bar (a); } the situation is similar for foo/bar (foo optimizes and doesn't zero extend from 8 to 32 bits, bar doesn't), but the caller in this case always zero extends.