https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81073
--- Comment #8 from Georg-Johann Lay <gjl at gcc dot gnu.org> --- (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 <avr/pgmspace.h> 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 &m; } 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 (&m->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 &m; } 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)(&m->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];}))); }