From 558617be42604d5a98938f153e990aec5b8484ed Mon Sep 17 00:00:00 2001 From: Ray Donnelly Date: Mon, 17 Aug 2015 22:57:46 +0100 Subject: [PATCH] clone_function_name_1: Retain any stdcall suffix Previously, clone_function_name_1 would add a suffix after any existing stdcall suffix, for example ipa-split.c would clone test@4 as test@4.part.0. Later, i386_pe_strip_name_encoding_full would come along and strip off everything from the last @ onwards which had the effect of generating incorrect section names which would then fall over with errors such as: error: void test() causes a section type conflict with \ void test@4.part.0() The following testcase, reduced from Firefox can be used to reproduce this. test.ii: class ClassA { public: virtual int __attribute__((__stdcall__)) Dispatch() = 0; }; class ClassB { public: ClassA* __attribute__((__stdcall__)) operator->(); }; class ClassC : ClassA { int *some_int_ptr_variable; int __attribute__((__stdcall__)) Dispatch() { return some_int_ptr_variable ? 42 : m_ClassInstanceB->Dispatch(); } ClassB m_ClassInstanceB; }; ClassC ClassInstanceC; Compile for i686-w64-mingw32 with: cc1plus -O -fpartial-inlining -fdevirtualize \ -fdevirtualize-speculatively test.ii Outputs: test.ii: In member function 'virtual int ClassC::Dispatch()': test.ii:11:36: error: virtual int ClassC::Dispatch() causes \ a section type conflict with int ClassC::_ZN6ClassC8DispatchEv@4.part.0() int __attribute__((CALLTYPE)) Dispatch() { ^ test.ii:11:36: note: \ 'int ClassC::_ZN6ClassC8DispatchEv@4.part.0()' was declared here --- gcc/cgraphclones.c | 13 ++++++++++++- gcc/defaults.h | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 07ceb1a..a2930a0 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -501,19 +501,30 @@ cgraph_node::create_clone (tree new_decl, gcov_type gcov_count, int freq, static GTY(()) unsigned int clone_fn_id_num; /* Return a new assembler name for a clone with SUFFIX of a decl named - NAME. */ + NAME. Final stdcall @N suffixes are maintained. */ tree clone_function_name_1 (const char *name, const char *suffix) { size_t len = strlen (name); char *tmp_name, *prefix; + const char *at_suffix = NULL; prefix = XALLOCAVEC (char, len + strlen (suffix) + 2); + /* name + 1 to skip fastcall which begins with '@' */ + at_suffix = strchr (name + 1, '@'); + size_t at_suffix_len = 0; + if (at_suffix) + { + at_suffix_len = strlen (at_suffix); + len -= at_suffix_len; + } memcpy (prefix, name, len); strcpy (prefix + len + 1, suffix); prefix[len] = symbol_table::symbol_suffix_separator (); ASM_FORMAT_PRIVATE_NAME (tmp_name, prefix, clone_fn_id_num++); + if (at_suffix) + strcat (tmp_name, at_suffix); return get_identifier (tmp_name); } diff --git a/gcc/defaults.h b/gcc/defaults.h index 3e18338..45d7192 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -51,7 +51,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ do { const char *const name_ = (NAME); \ char *const output_ = (OUTPUT) = \ - (char *) alloca (strlen (name_) + 32); \ + (char *) alloca (strlen (name_) + 35); \ sprintf (output_, ASM_PN_FORMAT, name_, (unsigned long)(LABELNO)); \ } while (0) #endif -- 2.7.4.windows.1