On the platform that add underscore before the external symbol, the name mangling in the following code generates different name for "testtemplate<int>::memberfunc()::memberfunclocalstaticvar const" with and without -O3. With -O3, the mangled name is incorrect. --<testinc.hxx>-- extern void func();
class testclass0 { public: testclass0(); ~testclass0(); private: int testvar; }; template< class testtemplatedummyparamclass > class testtemplate { public : testtemplate() { memberfunc(); } ~testtemplate() { memberfunc(); } private : testclass0& memberfunc() const { static testclass0 memberfunclocalstaticvar; return memberfunclocalstaticvar; } }; --<test1>-- #include "testinc.hxx" testtemplate< int > globalval; extern "C" { int main() { func(); return 0; } } --- Moreover, the following code always generates wrong mangled name, with or without -O3. --<test2.cxx>-- #include "testinc.hxx" testclass0::testclass0() { testvar=1; } testclass0::~testclass0() { } void func() { static testtemplate< int > funclocalstaticval; } --- If we link the object together, one of the sections for member function static variable will be discarded and either one of the reference will not be resolved. This will cause program crash. The behavior seems to be caused by the check in make_rtl_for_local_static in gcc/c-semantics fails if the name is mangled for C++ and the underscore is added in front. If we have a flag that indicates if the underscore is added, it is easy to solve the problem but we do not have it. The following patch will remedy the problem by mangling the name again and compare. --<mismangle.patch>-- --- gcc/c-semantics.c.orig 2004-08-28 16:20:48.000000000 +0900 +++ gcc/c-semantics.c 2005-08-07 18:13:46.000000000 +0900 @@ -231,6 +231,7 @@ make_rtl_for_local_static (tree decl) { const char *asmspec = NULL; + char *temp; /* If we inlined this variable, we could see it's declaration again. */ @@ -253,9 +254,19 @@ may as well not pass it in. If there isn't RTL, then we didn't already create RTL, which means that the modification to DECL_ASSEMBLER_NAME came only via the explicit extension. */ + if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl) && !DECL_RTL_SET_P (decl)) - asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + { + temp = alloca(strlen(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)))+1); + strcpy(temp, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); + change_decl_assembler_name(decl, NULL_TREE); + if (strcmp(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), temp)!=0) + { + change_decl_assembler_name(decl, get_identifier(temp)); + asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + } + } rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0); } --- gcc/cgraph.c.orig 2004-06-06 11:09:54.000000000 +0900 +++ gcc/cgraph.c 2005-08-07 17:59:16.000000000 +0900 @@ -523,6 +523,8 @@ vnode = NULL; } SET_DECL_ASSEMBLER_NAME (decl, name); + if (name != NULL_TREE) + { if (node) { slot = @@ -541,6 +543,7 @@ abort (); *slot = vnode; } + } } /* Try to find existing function for identifier ID. */ -- Summary: Name Mangling Problem Product: gcc Version: 3.4.2 Status: UNCONFIRMED Severity: critical Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: t_ono at hkfreak dot net http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26013