Bug 70435

Summary: section attribute of a function template is not honored.
Product: gcc Reporter: kukyakya
Component: c++Assignee: Patrick Palka <ppalka>
Status: RESOLVED FIXED    
Severity: normal CC: daniel.kruegler, david.hebbeker, headch, lists, lts-rudolph, mizvekov, msebor, ppalka, webrown.cpp
Priority: P3 Keywords: wrong-code
Version: 5.3.0   
Target Milestone: 14.0   
See Also: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88061
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41091
Host: Target:
Build: Known to work:
Known to fail: 5.3.0, 6.4.0, 7.3.0, 8.2.0, 9.0 Last reconfirmed: 2018-09-14 00:00:00

Description kukyakya 2016-03-29 12:38:41 UTC
namespace /* anonymous */
{
  [[gnu::section(".mysection")]]
  void regular_func() { }

  template <class T>
  [[gnu::section(".mysection")]]
  void template_func() { }
} // namespace /* anonymous */

void (*ptr1)() = &regular_func;
void (*ptr2)() = &template_func<int>;


In the code above the section attribute is given to both of the regular function and the function template, but the templated function is not placed in .mysection but .text.

$ g++ -std=c++14 a.cpp -c && objdump -t a.o | grep -E "regular|template"
0000000000000000 l     F .mysection	0000000000000007 _ZN12_GLOBAL__N_112regular_funcEv
0000000000000000 l     F .text	0000000000000007 _ZN12_GLOBAL__N_113template_funcIiEEvv
~/temp/c++/function_template_section $ 


I also tried it with clang and clang put the function into .mysection as I expected.


$ clang++ -std=c++14 a.cpp -c && objdump -t a.o | grep -E "regular|template"
0000000000000000 l     F .mysection	0000000000000006 _ZN12_GLOBAL__N_112regular_funcEv
0000000000000010 l     F .mysection	0000000000000006 _ZN12_GLOBAL__N_113template_funcIiEEvv
Comment 1 Armin van der Togt 2017-01-26 11:27:40 UTC
I am having the same problem with static member variables:

#include <sys/types.h>

class TestClassRegular {
public:
	static volatile const int32_t regularVar;
};
volatile const int32_t TestClassRegular::regularVar __attribute__ ((section(".eepromdata.ints"))) = 0;

template <uint32_t size, typename T>
class TestClassTemplate {
public:
	static volatile const int32_t templateVar;
};

template <uint32_t size, typename T>
volatile const int32_t TestClassTemplate<size,T>::templateVar  __attribute__ ((section(".eepromdata.ints"))) = 0;

int main() {
	int32_t blah = TestClassRegular::regularVar + TestClassTemplate<10, uint8_t>::templateVar;
	return blah;
}


 arm-none-eabi-objdump -t stm32l0-Template.elf | grep Var
200000c4  w    O .data	00000004 _ZN17TestClassTemplateILm10EhE11templateVarE
08080008 g     O .eepromdata	00000004 _ZN16TestClassRegular10regularVarE
Comment 2 Armin van der Togt 2017-04-08 13:57:50 UTC
Problem is still present in version 6.3.1
Comment 3 Matheus Izvekov 2018-08-02 06:54:05 UTC
Still an issue in gcc 8.2.0.
Comment 4 Martin Sebor 2018-09-14 19:12:52 UTC
Confirmed with the top of trunk.
Comment 5 Khalil 2018-09-25 15:22:30 UTC
Having similiar issues with ARM Embedded and Linux GCC. 
Having trouble finding a work around for this.
Here is an example code that demonstrates the issue in our particular use case:

===============================================================
// g++ -std=c++17 static.cpp -o static.exe
//
// objdump -t static.exe | grep thing
//     0000000000000740  u  O .rodata  0000000000000064 _ZZ5test0ILi5EEvvE5thing
//
// clang -std=c++14 static.cpp -o static.exe
// objdump -t static.exe  | grep thing
//     00000000004005d3 w O .log_entry 0000000000000064 _ZZ5test0ILi5EEvvE5thing

#include <cstdio>

#if __APPLE__
#define PUT_IN_SECTION(name) __attribute__((section("__text," name), used))
#else
#define PUT_IN_SECTION(name) __attribute__((section(name), used))
#endif

struct ThingType
{
  constexpr ThingType(const char * str): data{}
  {
    for(int i = 0; str[i] != '\0' && i < sizeof(data); i++)
    {
      data[i] = str[i];
    }
  }
  char data[100];
};

template <int dummy_template_parameter = 5>
void test0()
{
  PUT_IN_SECTION(".log_entry")
  static const ThingType thing("Goodbye!");
  printf("Hello, World!\n");
}

int main()
{
  test0();
  return 0;
}
===============================================================

Comment the test0 template line out, and the entry will appear in the 
appropriate section.
Comment 6 Felix Jones 2019-09-18 21:12:31 UTC
Related bug 88061

Here's a demonstration of the issue with GCC trunk x86-64 on godbolt: https://godbolt.org/z/9GFWZR

Minimal example for reproducing:
>  template <typename Type>
>  Type __attribute__( ( used, section( ".my_section" ) ) ) add_types( Type a, Type b ) {
>    return a + b;
>  }
>  
>  int main( int argc, char * argv[] ) {
>    return test_class<int>( s_value<3> ).add( add_types( 1, 2 ) );
>  }

Current behaviour: add_types within section .text
Desired behaviour: add_types within section .my_section

Clang trunk demonstrates the desired behaviour: https://godbolt.org/z/t8FNe0
Comment 7 Strager Neds 2019-11-06 23:09:33 UTC
I also encountered this bug. I started fixing this bug (and PR 88061): https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00348.html
Comment 8 Klaus Rudolph 2021-11-26 20:03:17 UTC
Bug still present in 11.2.1
Comment 9 GCC Commits 2023-12-15 15:04:30 UTC
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:ea7bebff7cc5a5eb780a6ca646cb77cad1b625d6

commit r14-6595-gea7bebff7cc5a5eb780a6ca646cb77cad1b625d6
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Dec 15 10:03:31 2023 -0500

    c++: section attribute on templates [PR70435, PR88061]
    
    The section attribute currently has no effect on templates because the
    call to set_decl_section_name only happens at parse time (on the
    dependent decl) and not also at instantiation time.  This patch fixes
    this by propagating the section name from the template to the
    instantiation.
    
            PR c++/70435
            PR c++/88061
    
    gcc/cp/ChangeLog:
    
            * pt.cc (tsubst_function_decl): Propagate DECL_SECTION_NAME
            via set_decl_section_name.
            (tsubst_decl) <case VAR_DECL>: Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/ext/attr-section1.C: New test.
            * g++.dg/ext/attr-section1a.C: New test.
            * g++.dg/ext/attr-section2.C: New test.
            * g++.dg/ext/attr-section2a.C: New test.
            * g++.dg/ext/attr-section2b.C: New test.
Comment 10 Patrick Palka 2023-12-16 17:16:48 UTC
Fixed for GCC 14