[Bug c++/81073] [5/6/7/8 Regression] link failure as C++ misses to instanciate some objects

2017-07-12 Thread gjl at gcc dot gnu.org
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

2017-07-12 Thread gjl at gcc dot gnu.org
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

2017-07-10 Thread jason at gcc dot gnu.org
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

2017-06-19 Thread gjl at gcc dot gnu.org
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

2017-06-19 Thread jason at gcc dot gnu.org
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

2017-06-19 Thread jason at gcc dot gnu.org
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

2017-06-19 Thread jason at gcc dot gnu.org
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

2017-06-17 Thread gjl at gcc dot gnu.org
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

2017-06-16 Thread jason at gcc dot gnu.org
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

2017-06-12 Thread redi at gcc dot gnu.org
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: jason 
Date:   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

2017-06-12 Thread redi at gcc dot gnu.org
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(){}