Hi! If DECL_LANG_SPECIFIC is created for a local var due to other reason than push_local_name, it might not have u.base.u2sel bit set and so DECL_DISCRIMINATOR can't be used on it (instead, should be assumed to be 0).
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, approved by Jason in the PR, committed to trunk. 2013-02-07 Jakub Jelinek <ja...@redhat.com> PR c++/56237 * decl.c (push_local_name): Look at DECL_DISCRIMINATOR (t) only if DECL_DISCRIMINATOR_SET_P (t) rather than just DECL_LANG_SPECIFIC (t). * g++.dg/abi/mangle61.C: New test. --- gcc/cp/decl.c.jj 2013-02-06 11:33:05.000000000 +0100 +++ gcc/cp/decl.c 2013-02-07 11:45:50.754972085 +0100 @@ -920,7 +920,7 @@ push_local_name (tree decl) if (!DECL_LANG_SPECIFIC (decl)) retrofit_lang_decl (decl); DECL_LANG_SPECIFIC (decl)->u.base.u2sel = 1; - if (DECL_LANG_SPECIFIC (t)) + if (DECL_DISCRIMINATOR_SET_P (t)) DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1; else DECL_DISCRIMINATOR (decl) = 1; --- gcc/testsuite/g++.dg/abi/mangle61.C.jj 2013-02-07 11:56:14.540241809 +0100 +++ gcc/testsuite/g++.dg/abi/mangle61.C 2013-02-07 11:56:04.000000000 +0100 @@ -0,0 +1,28 @@ +// PR c++/56237 +// { dg-do compile } + +void *p[4]; + +void +foo () +{ + static union { } u; + p[0] = &u; + { + static union { } u; + p[1] = &u; + { + static union { } u; + p[2] = &u; + } + } + { + static union { } u; + p[3] = &u; + } +} + +// { dg-final { scan-assembler "_ZZ3foovE1u\[^_\]" } } +// { dg-final { scan-assembler "_ZZ3foovE1u_0" } } +// { dg-final { scan-assembler "_ZZ3foovE1u_1" } } +// { dg-final { scan-assembler "_ZZ3foovE1u_2" } } Jakub