When building an executable with LTO, GCC effectively ignores __attribute__((section)) on C++ inline member functions. Moving such functions into the .text section seems to be intentional, but I think ignoring the section attribute is unintentional:
https://gcc.gnu.org/ml/gcc-patches/2010-07/msg00580.html > From: Jan Hubicka <hubicka at ucw dot cz> > > The patch uncovered two latent problems. [...] Also I think we > should clear NAMED_SECTION for comdats to conserve size. This is the > cgraph_make_decl_local change. Stop resetting the section of localized comdat symbols. This fixes __attribute__((section)) with -flto. Testing: Bootstrap on x86_64-linux-gnu with --disable-multilib --enable-checking=release --enable-languages=c,c++. Observe no change in test results (aside from the added tests). 2019-11-12 Matthew Glazar <strager....@gmail.com> * gcc/ipa-visibility.c (localize_node): Never set section_name to NULL. --- gcc/ipa-visibility.c | 4 --- .../ext/section-class-inline-function-lto.C | 17 +++++++++++ .../ext/section-class-inline-function.C | 25 ++++++++++++++++ gcc/testsuite/lib/scanasm.exp | 30 ++++++++++++++++++- 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C create mode 100644 gcc/testsuite/g++.dg/ext/section-class-inline-function.C diff --git gcc/ipa-visibility.c gcc/ipa-visibility.c index f470465f935..cf4c9101a2a 100644 --- gcc/ipa-visibility.c +++ gcc/ipa-visibility.c @@ -571,8 +571,6 @@ localize_node (bool whole_program, symtab_node *node) next != node; next = next->same_comdat_group) { next->set_comdat_group (NULL); - if (!next->alias) - next->set_section (NULL); if (!next->transparent_alias) next->make_decl_local (); next->unique_name @@ -595,8 +593,6 @@ localize_node (bool whole_program, symtab_node *node) if (TREE_PUBLIC (node->decl)) node->set_comdat_group (NULL); - if (DECL_COMDAT (node->decl) && !node->alias) - node->set_section (NULL); if (!node->transparent_alias) { node->resolution = LDPR_PREVAILING_DEF_IRONLY; diff --git gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C new file mode 100644 index 00000000000..4567d03a512 --- /dev/null +++ gcc/testsuite/g++.dg/ext/section-class-inline-function-lto.C @@ -0,0 +1,17 @@ +// attribute((section)) should affect inline member functions even with -flto. + +// { dg-do link } +// { dg-require-effective-target lto } +// { dg-require-named-sections "" } +// { dg-options "-flto --save-temps" } + +// { dg-final { scan-lto-assembler-symbol-section {callee} {^(\.testsection|__TEXT,__testsection)$} } } +#include "section-class-inline-function.C" + +// { dg-final { cleanup-saved-temps } } + +int +main() +{ + return f(); +} diff --git gcc/testsuite/g++.dg/ext/section-class-inline-function.C gcc/testsuite/g++.dg/ext/section-class-inline-function.C new file mode 100644 index 00000000000..01a12d02aff --- /dev/null +++ gcc/testsuite/g++.dg/ext/section-class-inline-function.C @@ -0,0 +1,25 @@ +// attribute((section)) should affect inline member functions. + +// { dg-do compile } +// { dg-require-named-sections "" } + +#if defined(__APPLE__) +#define TESTSECTION "__TEXT,__testsection" +#else +#define TESTSECTION ".testsection" +#endif + +// { dg-final { scan-assembler-symbol-section {callee} {^(\.testsection|__TEXT,__testsection)$} } } +struct s { + __attribute__((section(TESTSECTION))) + int callee() + { + return 0; + } +}; + +int +f() +{ + return s().callee(); +} diff --git gcc/testsuite/lib/scanasm.exp gcc/testsuite/lib/scanasm.exp index e9ebf52d77e..2eeb5b1e1fb 100644 --- gcc/testsuite/lib/scanasm.exp +++ gcc/testsuite/lib/scanasm.exp @@ -183,6 +183,29 @@ proc scan-assembler-symbol-section { args } { $expected_section_pattern } +# Check that symbols are emitted in the desired section. +# Like scan-assembler-symbol-section, but using the assembly output generated by +# the compiler with '-flto --save-temps'. +# +# Example: +# +# // All numbered functions (func1, func2, etc.) must be in the .text section or +# // in a .text sub-section (like .text._func1). +# { dg-final { scan-lto-assembler-symbol-section {^_func[1-5]$} {^\.text($|\.)} } } + +proc scan-lto-assembler-symbol-section { args } { + set testcase [testname-for-summary] + set output_file [lto_assembly_output_file $testcase] + set symbol_pattern [lindex $args 0] + set expected_section_pattern [lindex $args 1] + dg-scan-symbol-section \ + "scan-lto-assembler-symbol-section" \ + $testcase \ + $output_file \ + $symbol_pattern \ + $expected_section_pattern +} + # Check that symbols are emitted in the desired section. # # Symbols and sections are interpreted as regexp patterns. @@ -724,11 +747,16 @@ proc dg-function-on-line { args } { proc scan-lto-assembler { args } { set testcase [testname-for-summary] + set output_file [lto_assembly_output_file $testcase] + dg-scan "scan-lto-assembler" 1 $testcase $output_file $args +} + +proc lto_assembly_output_file { testcase } { # The name might include a list of options; extract the file name. set filename [lindex $testcase 0] set output_file "[file rootname [file tail $filename]].exe.ltrans0.s" verbose "output_file: $output_file" - dg-scan "scan-lto-assembler" 1 $testcase $output_file $args + return $output_file } # Read assembly file FILENAME and store a mapping from function names -- 2.22.0