https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116433
Bug ID: 116433 Summary: [AVR] cannot place template class static members in EEPROM Product: gcc Version: 13.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: digger1984 at gmx dot com Target Milestone: --- Created attachment 58963 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=58963&action=edit Complete sample code with three separate use cases Context I designed a template class in the hope it could make EEPROM storage somehow transparent by implementing read and write accessors in a class/struct. The desired goal is equivalent to this: eemem<initial_value> variable; foo(variable); The compiler would then automatically fetch the value for the internal variable before passing it to function `foo`. Otherwise the conventional approach is: auto variable EEMEM = initial_value; foo(eeprom_read_<appropriate_b_w_d_idom>(&variable)); And so on for every similar situation. Same goes with writing but even more verbose. I'm using C++ ability to supply literals as template arguments. From there the type is deduced from the argument. In order to achieve what I want(ed) I need a static member variable to which I append the EEMEM macro for EEPROM storage. For the reference I've used the same tactics for program memory storage and it works as expected, therefore I hoped it would also work for EEPROM storage. The problem AVR-GCC version 13.2.0 ignores the section attribute and instead places static members of template classes in RAM, which is not the desired effect. I've looked up bugs #89148, #116184 and #87178 to find an explanation (I *think* I understand the issue but I'm not quite sure). Here's a minimal example to illustrate the problem: template <auto V> struct eemem { typedef type::remove_cv_t<decltype(V)> value_type; static value_type value __attribute__((section(".eeprom"), used)); }; template<auto V> eemem<V>::value_type eemem<V>::value __attribute__((section(".eeprom"), used)) = V; eemem<69U> test; Note this is *not* the full class definition; I stripped it to the bare minimum for illustration purposes. When accessed from function `main` like this: PORTB = eeprom_read_word(&test.value); the compiled code appears as follows (also note there's no warning nor errors at compile time): ba: 80 e0 ldi r24, 0x00 ; 0 bc: 91 e0 ldi r25, 0x01 ; 1 be: 0e 94 65 00 call 0xca ; 0xca <eeprom_read_word> c2: 85 b9 out PORTB, r24 ; 5 I'd understand if this bug is marked as a duplicate but I'd like to stress on the fact that I'm not trying to move my variables into a section of my own, only into what's been defined for the AVR platform as to EEPROM storage. So if this is not possible, is there a workaround (e.g. with a custom linker script, maybe)? Attached is the complete test code I. Compiler command line options are: -Os -mmcu=atmega328p -std=gnu++20 -DF_CPU=16000000 Only the non-template class has its static member variable stored in EEPROM, as expected. The other two have their member variable stored in RAM, which is undesired. Also note with AVR-GCC 14.1.0 (from Matt Godbolt Compiler Explorer) I get the following error message: <source>:46:35: error: 'stg::t2::eemem::value' causes a section type conflict with 'stg::t3::eemem<unsigned int>::value' Best, C.F.