Bootstrapped and regtested on x86_64-redhat-linux and s390x-redhat-linux. Ok for master (or GCC 13 in case this doesn't fit stage4 criteria)?
Building C++ template-heavy code with ASan sometimes leads to bogus "defined in discarded section" linker errors. The reason is that .rodata.FUNC.cstN sections are not placed into COMDAT group sections FUNC. This is important, because ASan puts references to .LASANPC labels into these sections. Discarding the respective .text.FUNC section causes the linker error. Fix by adding SECTION_LINKONCE to .rodata.FUNC.cstN sections in mergeable_constant_section () if the current function has an associated COMDAT group. This is similar to what switch_to_exception_section () is currently doing with .gcc_except_table.FUNC sections. gcc/ChangeLog: * varasm.cc (mergeable_constant_section): Honor COMDAT. gcc/testsuite/ChangeLog: * g++.dg/asan/comdat.C: New test. --- gcc/testsuite/g++.dg/asan/comdat.C | 35 ++++++++++++++++++++++++++++++ gcc/varasm.cc | 6 ++++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/asan/comdat.C diff --git a/gcc/testsuite/g++.dg/asan/comdat.C b/gcc/testsuite/g++.dg/asan/comdat.C new file mode 100644 index 00000000000..cd4f3f830a8 --- /dev/null +++ b/gcc/testsuite/g++.dg/asan/comdat.C @@ -0,0 +1,35 @@ +/* Check that we don't emit non-COMDAT rodata. */ + +/* { dg-do compile } */ +/* { dg-final { scan-assembler-not {\.section\t\.rodata\._ZN1hlsIPKcEERS_RKT_\.cst[48],"[^"]*",@progbits,[48]\n} } } */ + +const char *a; + +class b +{ +public: + b (); +}; + +class h +{ +public: + template <typename c> + h & + operator<< (const c &) + { + d (b ()); + return *this; + } + + void d (b); +}; + +h e (); + +h +g () +{ + e () << a << a << a; + throw; +} diff --git a/gcc/varasm.cc b/gcc/varasm.cc index c41f17d64f7..f2614f0ee39 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -938,7 +938,11 @@ mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED, sprintf (name, "%s.cst%d", prefix, (int) (align / 8)); flags |= (align / 8) | SECTION_MERGE; - return get_section (name, flags, NULL); + if (current_function_decl + && DECL_COMDAT_GROUP (current_function_decl) + && HAVE_COMDAT_GROUP) + flags |= SECTION_LINKONCE; + return get_section (name, flags, current_function_decl); } return readonly_data_section; } -- 2.35.1