[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #11 from Georg-Johann Lay --- ...oops, I missed the PROGMEM in PSTR definition. Should read: // A string in flash #define PSTR(str) \ (__extension__({ \ static const char __c[] PROGMEM = (str); \ &__c[0]; \ })) but still no error.
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #10 from Georg-Johann Lay --- (In reply to Jason Merrill from comment #9) > Created attachment 41711 [details] > patch to error on progmem with dynamic init > > Does this do what you had in mind? Some situations are diagnosed, but already something like in this PR passes your test und dynamically initializes __c in .rodata: #define PROGMEM __attribute__((__progmem__)) // A string in flash #define PSTR(str) \ (__extension__({ \ static const char __c[] = (str); \ &__c[0]; \ })) typedef struct { char id; const char *labl; } menu_t; const menu_t* setup_Flash (void) { static const menu_t menu PROGMEM = { 123, PSTR ("in Flash") }; return } int main(){} So either this should be diagnosed or deflate similar to const menu_t* setup_RAM (void) { static const menu_t menu PROGMEM = { 123, "in RAM" }; return }
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #9 from Jason Merrill --- Created attachment 41711 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=41711=edit patch to error on progmem with dynamic init Does this do what you had in mind?
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #8 from Georg-Johann Lay --- (In reply to Jason Merrill from comment #7) > > To make things even worse, all the PROGMEM + inline asm + > > statement-expression stuff is hidden behind common usability macros that are > > used by actually every avr-g++ user like Arduino. > > Hmm. Which macros? It's macros from AVR-LibC, the only C-library used for AVR. http://nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html The statement expression is introduced by PSTR. For example: #include struct menu { int id; const char *text; }; // m and m->text will reside in flash. extern const menu* get_menu() { static const menu m PROGMEM = { 1, PSTR ("Hallo") }; return } extern void print_prog_string (const char *s); // m and m->text must reside in flash, otherwise (e.g. .rodata) code // will print garbage. extern void print_something (const menu *m) { const char *str = (const char*) pgm_read_word (>text); print_prog_string (str); print_prog_string (PSTR ("some text")); } PSTR is used to cook up a string in flash and yields its address. Any read from flash must be performed by inline asm, here by pgm_read_word macro. print_prog_string() similarly must use pgm_read_byte to retrieve chars from flash. Just *s would read from RAM and get garbage. The code expands to (snipped for legibility): typedef unsigned int uint8_t __attribute__((__mode__(__QI__))); typedef unsigned int uint16_t __attribute__ ((__mode__ (__HI__))); struct menu { int id; const char *text; }; extern const menu* get_menu() { static const menu m __attribute__((__progmem__)) = { 1, (__extension__({static const char __c[] __attribute__((__progmem__)) = ("Hallo"); &__c[0];})) }; return } extern void print_prog_string (const char *s); extern void print_something (const menu *m) { const char *str = (const char*) (__extension__( { uint16_t __addr16 = (uint16_t)((uint16_t)(>text)); uint16_t __result; __asm__ __volatile__ ("lpm %A0, Z+" "\n\t" "lpm %B0, Z" "\n\t" : "=r" (__result), "=z" (__addr16) : "1" (__addr16) ); __result; } )); print_prog_string (str); print_prog_string ((__extension__({static const char __c[] __attribute__((__progmem__)) = ("some text"); &__c[0];}))); }
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #7 from Jason Merrill --- (In reply to Georg-Johann Lay from comment #4) > I would already be happy if the AVR backend could diagnose situation where > C++ magic shreds assumptions of const + PROGMEM. That would be good. > In order to make clear what the user *really needs* (something that's > *really* const so it could reside in flash) and to show the problem on x86, > I switched from const to constexpr -- however I am not a C++ guy... This makes sense to me; declaring a variable constexpr requires constant initialization. The problem with the testcase is burying the declaration in a statement-expression. > To make things even worse, all the PROGMEM + inline asm + > statement-expression stuff is hidden behind common usability macros that are > used by actually every avr-g++ user like Arduino. Hmm. Which macros?
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #6 from Jason Merrill --- Author: jason Date: Mon Jun 19 18:20:48 2017 New Revision: 249383 URL: https://gcc.gnu.org/viewcvs?rev=249383=gcc=rev Log: PR c++/81073 - constexpr and static var in statement-expression. * constexpr.c (cxx_eval_constant_expression) [DECL_EXPR]: Check potential_constant_expression. Added: branches/gcc-7-branch/gcc/testsuite/g++.dg/ext/stmtexpr19.C Modified: branches/gcc-7-branch/gcc/cp/ChangeLog branches/gcc-7-branch/gcc/cp/constexpr.c
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #5 from Jason Merrill --- Author: jason Date: Mon Jun 19 18:20:10 2017 New Revision: 249382 URL: https://gcc.gnu.org/viewcvs?rev=249382=gcc=rev Log: PR c++/81073 - constexpr and static var in statement-expression. * typeck2.c (store_init_value): Always call require_potential_constant_expression. * pt.c (convert_nontype_argument): Likewise. * constexpr.c (potential_constant_expression_1): Adjust message. Use decl_maybe_constant_var_p instead of decl_constant_var_p. * decl2.c (decl_maybe_constant_var_p): Consider initializer. Added: trunk/gcc/testsuite/g++.dg/ext/stmtexpr19.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/cp/decl2.c trunk/gcc/cp/pt.c trunk/gcc/cp/typeck2.c trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial2.C
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 --- Comment #4 from Georg-Johann Lay --- (In reply to Jason Merrill from comment #3) > The testcase in comment 1 works on trunk and current 7 branch. The original > testcase looks ill-formed to me; [dcl.constexpr] says that a constexpr > function can't define a variable with static storage duration, and I think > the same applies to statement-expressions, for the same reason: when we > optimize to a constant value, we no longer have the declaration, which leads > to link errors like this. Some more background: It's a condensed C++ test case from AVR that looked something like this: #defin PROGMEM __attribute__((__progmem__)) struct test { const int *addr; }; const test* setup() { static const test atest PROGMEM = { ({ static const int inner PROGMEM = 123; }) }; return } int main(){} PROGMEM is similar to section attribute and puts data into flash section which cannot be written at run-time. As C++ doesn't support named address spaces like __flash, data must be read by inline assembly that emits special instructions that perform reading from flash (reading from flash / RAM requires different instructions and addressing modes). This is needed because .rodata must be loaded to RAM, and in order so save very precious RAM that might be only some bytes depending on device. The trouble with "const" is that const in C++ is not really const (like a const in static storage in C that is .rodata or optimized away) but might need constructing, and the backend won't see whether C++ will cook up a constructor. In that case the backend could issue an error, but the current state of affairs is that constructing leads to wrong code because TARGET_INSERT_ATTRIBUTES cannot diagnose on that situation. What's the right hook to issue a diagnostic if a const object in static storage needs constructing? I would already be happy if the AVR backend could diagnose situation where C++ magic shreds assumptions of const + PROGMEM. In order to make clear what the user *really needs* (something that's *really* const so it could reside in flash) and to show the problem on x86, I switched from const to constexpr -- however I am not a C++ guy... To make things even worse, all the PROGMEM + inline asm + statement-expression stuff is hidden behind common usability macros that are used by actually every avr-g++ user like Arduino.
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 Jason Merrill changed: What|Removed |Added Status|NEW |ASSIGNED Assignee|unassigned at gcc dot gnu.org |jason at gcc dot gnu.org --- Comment #3 from Jason Merrill --- The testcase in comment 1 works on trunk and current 7 branch. The original testcase looks ill-formed to me; [dcl.constexpr] says that a constexpr function can't define a variable with static storage duration, and I think the same applies to statement-expressions, for the same reason: when we optimize to a constant value, we no longer have the declaration, which leads to link errors like this.
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 Jonathan Wakely changed: What|Removed |Added CC||jason at gcc dot gnu.org --- Comment #2 from Jonathan Wakely --- r217662 is correct (i.e. defines the variable), r217663 gives an ICE, which persists until r217748 which compiles it again but fails to define the variable. commit da7981e061ae97c7f83ed4ace5cf725e6fe0cffb Author: jasonDate: Wed Nov 19 03:03:39 2014 + * constexpr.c (cxx_eval_statement_list): Handle statement-expressions. (potential_constant_expression_1): Handle STMT_EXPR. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@217748 138bc75d-0d04-0410-961f-82ee72b054a4
[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073 Jonathan Wakely changed: What|Removed |Added Status|UNCONFIRMED |NEW Last reconfirmed||2017-06-12 Known to work||4.9.4 Summary|link failure as C++ misses |[5/6/7/8 Regression] link |to instanciate some objects |failure as C++ misses to ||instanciate some objects Ever confirmed|0 |1 Known to fail||5.4.0, 6.3.0, 7.1.0, 8.0 --- Comment #1 from Jonathan Wakely --- C++98 version that compiles fine with versions before 5.1.0 struct test { const int *addr; }; const test* setup() { static const test atest = { ({ static const int inner = 123; }) }; return } int main(){}