summaryrefslogtreecommitdiffstats
path: root/PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch
diff options
context:
space:
mode:
Diffstat (limited to 'PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch')
-rw-r--r--PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch109
1 files changed, 109 insertions, 0 deletions
diff --git a/PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch b/PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch
new file mode 100644
index 0000000..e196f24
--- /dev/null
+++ b/PATCHES/0014-clone_function_name_1-Retain-any-stdcall-suffix.patch
@@ -0,0 +1,109 @@
+From 558617be42604d5a98938f153e990aec5b8484ed Mon Sep 17 00:00:00 2001
+From: Ray Donnelly <mingw.android@gmail.com>
+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
+