[Bug middle-end/59448] Code generation doesn't respect C11 address-dependency

2014-02-17 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #11 from algrant at acm dot org ---
Where do you get that this is racy if the access to data is not atomic?  By
design, release/acquire and release/consume sequences don't require wholesale
changes to the way the data payload (in the general case, multiple fields
within a structure) is first constructed and then used.  1.10#13 makes clear
that as a result of the intra-thread sequencing between atomic and non-atomic
operations (1.9#14), and the inter-thread ordering between atomic operations
(1.10 various), there is a resulting ordering on operations to ordinary (sic)
objects.  Please see the references to the C++ standard in the source example,
for the chain of reasoning here.


[Bug middle-end/59448] Code generation doesn't respect C11 address-dependency

2014-02-17 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #13 from algrant at acm dot org ---
I see what you mean - there is a race if threadB reads the data when the
flag is not set, i.e. in the case when the read value is never used.
Moving the read of data after the test (as in the fragment in comment 4)
would fix the race.


[Bug middle-end/59448] Code generation doesn't respect C11 address-dependency

2014-01-20 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #6 from algrant at acm dot org ---
Here is a complete C++11 test case.  The code generated for the two loads
in thread B doesn't maintain the required ordering:

...
ldrbw1, [x0]
uxtbw1, w1
adrpx0, .LANCHOR0
ldr w2, [x3]
...

According to the architecture specification, to achieve the ordering it's
sufficient to use the result of the first load in the calculation of the
address of the second, even if it's done in such a way as to have no
dependence on the value.

/* Reproducer for 59448: compile with -std=c++11 -lpthread */

#include atomic
#include thread
#include stdio.h
#include assert.h

static std::atomicbool flag(0);
static int data;

/*
Thread A tries to release a data value 1 to thread B via a
release/consume sequence.

In the demonstration, this is tried repeatedly.  The iterations of
the two threads are synchronized via a release/acquire sequence
from B to A.  This is not relevant to the ordering problem.
*/

void threadA(void)
{
  for (;;) {
data = 1;   // A.A
flag.store(1, std::memory_order_release);   // A.B
/* By 1.9#14, A.A is sequenced before A.B */
/* Now wait for thread B to accept the data. */
while (flag.load(std::memory_order_acquire) == 1);
assert(data == 0);
  }
}

void threadB(void)
{
  for (;;) {
int f, d;
do {
  f = flag.load(std::memory_order_consume); // B.A
  d = *(data + f - f); // B.B
  /* By 1.10#9, B.A carries a dependency to B.B */
  /* By 1.10#10, A.B is dependency-ordered before B.B */
  /* By 1.10#11, A.A intra-thread happens before B.B */
  /* By 1.10#12, A.A happens before B.B */
  /* By 1.10#13, A.A is a visible side-effect with respect to B.B
 and the value determined by B.B shall be the
 value (1) stored by A.A. */
} while (!f);
assert(d == 1);
/* Release thread A to start another iteration. */
data = 0;
flag.store(0, std::memory_order_release);
  }
}

int main(void)
{
  std::thread a(threadA);
  std::thread b(threadB);
  a.join();
  b.join();
  return 0;
}


[Bug middle-end/59448] Code generation doesn't respect C11 address-dependency

2014-01-20 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #8 from algrant at acm dot org ---
I don't see how f can not be 0 or 1 here, but to make this even more clear
that there is no UB, define flag this way:

  static std::atomicunsigned int flag(0);

and calculate the address this way:

  d = *(data + (f - f)); // B.B

The ordering requirements are the same, and there is no possibility of UB.


[Bug middle-end/59448] Code generation doesn't respect C11 address-dependency

2013-12-12 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #4 from algrant at acm dot org ---
So using g++,

  #include atomic
  int f1(std::atomicint const *p, std::atomicint const *q)
  {
int flag = p-load(std::memory_order_consume);
return flag ? (q + flag - flag)-load(std::memory_order_relaxed) : 0;
  }

demonstrates the same lack of ordering.  You suggest that this might
be a problem with the atomic built-ins - and yes, if this had been a
load-acquire, it would be a problem with the built-in not introducing a
barrier or using a load-acquire instruction.  But for a load-consume on
this architecture, no barrier is necessary to separate the load-consume
from a load that is address-dependent on it.  The programmer wrote a
dependency but the compiler lost track of it.

It's not necessary to demonstrate failure - there's an architectural 
race condition here.  Even if it doesn't fail now there's no guarantee
it will never fail on future more aggressively reordering cores.


[Bug target/59448] New: ARM code generation doesn't respect C11 address-dependency

2013-12-10 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

Bug ID: 59448
   Summary: ARM code generation doesn't respect C11
address-dependency
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: algrant at acm dot org

int f2(int const *p, int const *q)
  {
int flag = *p;
return flag ? *(q + flag - flag) : 0;
  }

The evaluation *(q + flag - flag) is ordered after *p by 5.1.2.4#14;
writing it this way is a recognized way of forcing the ordering.
AArch64 GCC 4.8 -O2 --std=c11 generates

f2:
ldr w2, [x0]
mov w0, 0
cbz w2, .L2
ldr w0, [x1]
.L2

which doesn't preserve the ordering in the target memory model.
The compiler needs to introduce an address dependency, e.g.

and w2, w2, #0
ldr w0, [x1, w2]

or insert a memory barrier instruction.  According to the target
architecture's own rules, this is sufficient to order the loads.

In general, the C source-level address dependency (defined by the 
syntactic rules of 5.1.2.4#14) might not involve arithmetic.
For example:

  inline int makedep(int flag, ...) { return flag; }  // variadic

  int f3(int const *p, int const *q) {
int flag = *p;
return flag ? makedep(*q, flag) : 0;
  }

An access might even be formally dependent on multiple expressions.
The compiler just has to keep track.


[Bug c/59448] Code generation doesn't respect C11 address-dependency

2013-12-10 Thread algrant at acm dot org
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59448

--- Comment #2 from algrant at acm dot org ---
Just realised that that last example is bogus, it should read:

  inline int const *makedep(int const *a, ...) { return a; }  // variadic

  int f3(int const *p, int const *q) {
int flag = *p;
return flag ? *makedep(q, flag) : 0;
  }

In C++, makedep could be a template - the counterpart of kill_dependency.


[Bug c/39488] ARM ABI: enum comparison against zero optimized away

2009-03-18 Thread algrant at acm dot org


--- Comment #2 from algrant at acm dot org  2009-03-18 09:45 ---
No, the enum is signed, see AAPCS 7.1.3: the container type is int
unless the upper bound is greater than 2147483647.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39488



[Bug c/39488] New: ARM ABI: enum comparison against zero optimized away

2009-03-18 Thread algrant at acm dot org
With ARM ABI variant selected by -fno-short-enums the compare shouldn't
be optimized away:

  enum RC { X, Y, Z };
  int check_error(enum RC a) { return a  0; }

C 6.3#2 guarantees that any value of the compatible type can be assigned
to and from values of the enumerator type with no change to the value or
the representation.  So if the implementation defines the compatible 
type to be a signed type (which ARM ABI -fno-short-enums does in this case,
see AAPCS 7.1.3), objects of the enumerator type can validly have negative
values and the test is not redundant.  (Of course, a strictly conforming
program cannot rely on this or any other property of the ABI.)

(Aside: this optimization is valid for C++, following 7.2#6.)


-- 
   Summary: ARM ABI: enum comparison against zero optimized away
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org
GCC target triplet: arm-none-eabi-gcc


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39488



[Bug c/39430] New: GCC does not put 'const auto' structure on the stack

2009-03-11 Thread algrant at acm dot org
This code creates an 'activation record' structure for each active
call to the function:

  struct frame { char const *name; int line; };
  extern void trace(struct frame const *);
  int f(int n) {
const struct frame v = { __FUNCTION__, __LINE__ };
trace(v);
return n ? n*f(n-1) : 1;
  }

These should be distinct, i.e. their addresses are distinct to
any observer.  But GCC evaluates v to refer to one instance in
static storage.  Surely the standard doesn't allow an implementation
to do this.  It doesn't happen if 'v' is not marked 'const'.


-- 
   Summary: GCC does not put 'const auto' structure on the stack
   Product: gcc
   Version: 4.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39430



[Bug c++/39415] New: static_cast used as downcast can silently lose const

2009-03-09 Thread algrant at acm dot org
This is silently accepted:

  struct T { };
  struct T_impl: public T { };
  T_impl *g(T *tp) { return static_castconst T_impl*(tp); }

The result type of the static_cast is pointer-to-const and should not
convert to a pointer-to-non-const.  This seems to be specific to when
it is used as a downcast.  Replacing the last line with

  T *g(T *tp) { return static_castconst T*(tp); }

is faulted as expected.


-- 
   Summary: static_cast used as downcast can silently lose const
   Product: gcc
   Version: 4.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39415



[Bug c/39383] sizeof object with zero-length array ignores initializer

2009-03-06 Thread algrant at acm dot org


--- Comment #6 from algrant at acm dot org  2009-03-06 14:44 ---
Right.  The existence of a statically initialized object whose size can
be determined at compile-time to be larger than the (notional) type size,
is specific to GCC.  Here's another thing: the assembler output shows

.type   f1, %object
.size   f1, 4
f1:
.word   1
.word   2
.word   3
.word   4

Whatever you think about sizeof(), surely the object's symbol should
have its true size (16 in this case)?


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39383



[Bug c/39383] New: sizeof object with zero-length array ignores initializer

2009-03-05 Thread algrant at acm dot org
Example from docs: 
  struct f1 { int x; int y[]; } f1 = { 1, { 2, 3, 4 } };
Currently sizeof(f1) == sizeof(int) rather than 4*sizeof(int), i.e.
sizeof the object is determined by the type only, not the actual object
size taking into account its initializer.  If this is intentional the
docs could benefit from clarification, as otherwise it's natural to
want to use sizeof to find out how big the object actually ended up as.


-- 
   Summary: sizeof object with zero-length array ignores initializer
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39383



[Bug c/39383] sizeof object with zero-length array ignores initializer

2009-03-05 Thread algrant at acm dot org


--- Comment #2 from algrant at acm dot org  2009-03-05 13:19 ---
No, the case is an extension to C.  6.5.3.4 was obviously written without
this case in mind.  In this case the size... of its operand cannot be
determined from the type.  Either sizeof doesn't return the (real) size
of the operand, or it isn't determined from the type.  Current GCC behavior
is to have it not return the size of the operand.  That's a valid point of 
view but it does mean one needs to take care when using sizeof on such
objects, and it's worth documenting.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39383



[Bug c/39384] New: sizeof object with zero-length array ignores initializer

2009-03-05 Thread algrant at acm dot org
Example from docs: 
  struct f1 { int x; int y[]; } f1 = { 1, { 2, 3, 4 } };
Currently sizeof(f1) == sizeof(int) rather than 4*sizeof(int), i.e.
sizeof the object is determined by the type only, not the actual object
size taking into account its initializer.  If this is intentional the
docs could benefit from clarification, as otherwise it's natural to
want to use sizeof to find out how big the object actually ended up as.


-- 
   Summary: sizeof object with zero-length array ignores initializer
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39384



[Bug c/39384] sizeof object with zero-length array ignores initializer

2009-03-05 Thread algrant at acm dot org


--- Comment #1 from algrant at acm dot org  2009-03-05 14:48 ---
Unwanted duplicate entry of 39383 caused by refreshing browser page.

*** This bug has been marked as a duplicate of 39383 ***


-- 

algrant at acm dot org changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution||DUPLICATE


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39384



[Bug c/39383] sizeof object with zero-length array ignores initializer

2009-03-05 Thread algrant at acm dot org


--- Comment #5 from algrant at acm dot org  2009-03-05 14:48 ---
*** Bug 39384 has been marked as a duplicate of this bug. ***


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39383



[Bug c/38397] New: gcc -E -dD changes the meaning of source

2008-12-04 Thread algrant at acm dot org
compile with -E -dD:

  enum { A, B };
  #define B A
  #define A B+1
  int x = A;

This will print something like

  enum { A, B };
  #define B A
  #define A B+1
  int x = A+1;

This defines x as 2 instead of 1.  Recycle the output bad in and
x gets bigger and bigger.

Although it doesn't seem to be formally defined that the output
of -E -dD is valid source code equivalent to the original,
the output is presented as if it is.  There are at least two
solutions:

- present the #define and #undef as comments

- suppress macro expansion when -dD is used

The ability to suppress macro expansion is a useful feature in
its own right and could make some sources more readable, when the
intention of -E is simply to flatten the input.


-- 
   Summary: gcc -E -dD changes the meaning of source
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=38397



[Bug c++/37697] New: dynamic_cast to void cv* wrongly allowed with -fno-rtti

2008-10-01 Thread algrant at acm dot org
Compiled -fno-rtti, g2 and g3 are faulted but g1 is not.  Code for g1
(on ARM target) shows use of RTTI which we have asserted is absent.

struct B1 { virtual int f(); };
struct B2 { virtual int g(); };
struct D: B1, B2 { };

/* These should be allowed even with -fno-rtti */
B1 *f2(B1 *p) { return dynamic_castB1 *(p); }
B1 *f3(D *p) { return dynamic_castB1 *(p); }

/* These should not be allowed with -fno-rtti */
/* gABI 2.9.4 case #1: dynamic castvoid cv*, which returns a pointer to the
complete lvalue */
void *g1(B1 *p) { return dynamic_castvoid *(p); }
/* gABI 2.9.4 case #2: dynamic cast operation from a proper base class to a
derived clasB1 */
D *g2(B1 *p) { return dynamic_castD *(p); }
/* gABI 2.9.4 case #3: dynamic_cast across the hierarchy which can be seen as a
cast to the complete lvalue and back to a sibling base */
B1 *g3(B2 *p) { return dynamic_castB1 *(p); }


-- 
   Summary: dynamic_cast to void cv* wrongly allowed with -fno-rtti
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org
GCC target triplet: ARM


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37697



[Bug c++/37701] New: dynamic_cast to void cv* wrongly allowed with -fno-rtti

2008-10-01 Thread algrant at acm dot org
Compiled -fno-rtti, g2 and g3 are faulted but g1 is not.  Code for g1
(on ARM target) shows use of RTTI which we have asserted is absent.

struct B1 { virtual int f(); };
struct B2 { virtual int g(); };
struct D: B1, B2 { };

/* These should be allowed even with -fno-rtti */
B1 *f2(B1 *p) { return dynamic_castB1 *(p); }
B1 *f3(D *p) { return dynamic_castB1 *(p); }

/* These should not be allowed with -fno-rtti */
/* gABI 2.9.4 case #1: dynamic castvoid cv*, which returns a pointer to the
complete lvalue */
void *g1(B1 *p) { return dynamic_castvoid *(p); }
/* gABI 2.9.4 case #2: dynamic cast operation from a proper base class to a
derived clasB1 */
D *g2(B1 *p) { return dynamic_castD *(p); }
/* gABI 2.9.4 case #3: dynamic_cast across the hierarchy which can be seen as a
cast to the complete lvalue and back to a sibling base */
B1 *g3(B2 *p) { return dynamic_castB1 *(p); }


-- 
   Summary: dynamic_cast to void cv* wrongly allowed with -fno-rtti
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org
GCC target triplet: ARM


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37701



[Bug c++/37697] dynamic_cast to void cv* wrongly allowed with -fno-rtti

2008-10-01 Thread algrant at acm dot org


--- Comment #1 from algrant at acm dot org  2008-10-01 15:35 ---
*** Bug 37701 has been marked as a duplicate of this bug. ***


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37697



[Bug c++/37701] dynamic_cast to void cv* wrongly allowed with -fno-rtti

2008-10-01 Thread algrant at acm dot org


--- Comment #1 from algrant at acm dot org  2008-10-01 15:35 ---


*** This bug has been marked as a duplicate of 37697 ***


-- 

algrant at acm dot org changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution||DUPLICATE


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37701



[Bug c++/37697] dynamic_cast to void cv* wrongly allowed with -fno-rtti

2008-10-01 Thread algrant at acm dot org


--- Comment #2 from algrant at acm dot org  2008-10-01 16:40 ---
Bug report in error.


-- 

algrant at acm dot org changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution||INVALID


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37697



[Bug c++/36685] New: clarify/diagnose use of weak constant

2008-07-01 Thread algrant at acm dot org
Consider this:

  __attribute__((weak)) extern int const K = 7;
  int f(void) { return K; }
  int a[K];

Assuming the combination of 'weak' and 'const' is legitimate
(and it seems useful enough to allow), the compiler should avoid
the constant-promotion optimization when generating f(), and
should fault a[].


-- 
   Summary: clarify/diagnose use of weak constant
   Product: gcc
   Version: 4.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36685



[Bug c++/36685] clarify/diagnose use of weak constant

2008-07-01 Thread algrant at acm dot org


--- Comment #1 from algrant at acm dot org  2008-07-01 10:21 ---
Similar argument applies to __attribute__((visibility(default))) .


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36685



[Bug c++/27141] [4.0/4.1/4.2 Regression] Unexpected requirement for usual deallocation function

2006-05-02 Thread algrant at acm dot org


--- Comment #2 from algrant at acm dot org  2006-05-02 07:20 ---
Actually, I now wonder if the g++ 4.1 behavior would be correct
by the proposed resolution of (still open) Core Language Issue 252.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27141



[Bug c++/27141] New: Unexpected requirement for usual deallocation function

2006-04-13 Thread algrant at acm dot org
This code:

  struct D {
  D() {}
  virtual ~D() {}
  void operator delete(void*, void*) {}
  };
  void f() { D d(); }

is rejected with no suitable 'operator delete' for 'D'.
It is true that the placement deallocation function hides any
usual one, but surely it is only necessary for a usual one to
be found when implementing a delete-expression, as described
in 12.5#4.  This code is accepted by Comeau and HP aC++ (but
faulted by Sun C++ with a similar error to g++).


-- 
   Summary: Unexpected requirement for usual deallocation function
   Product: gcc
   Version: 4.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27141



[Bug c/26841] New: extern inline fails to create external definition in C99 mode

2006-03-24 Thread algrant at acm dot org
In C99 this
  extern inline int f(int n) { return n + 1; }
does not meet the criteria in 6.7.4#6 for 'inline definition'
and is therefore an external definition.  gcc -std=c99 fails
to emit an external definition, though it does for the
separate definition/declaration case in the 6.7.4#7 example.


-- 
   Summary: extern inline fails to create external definition in C99
mode
   Product: gcc
   Version: 4.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org
 GCC build triplet: -std=c99


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26841



[Bug c++/21025] New: ICE on template

2005-04-14 Thread algrant at acm dot org
3.4.3 seg faults on this:

  templateint N struct X { char x[N]; };
  templatetypename T X1 + sizeof(T) - sizeof(T) F(T const );
  templateint N struct S { int d() { F(1); } };

Appears to be quite dependent on the fact that the template argument
involves sizeof(T) - sizeof(T) - if the - is changed to a +, it works.
Ok in 3.3.2, and ok if S is not a template.

-- 
   Summary: ICE on template
   Product: gcc
   Version: 3.4.3
Status: UNCONFIRMED
  Severity: normal
  Priority: P2
 Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: algrant at acm dot org
CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21025