[Bug c++/109795] New: is_standard_layout incorrect for colliding member and base class

2023-05-09 Thread myriachan at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109795

Bug ID: 109795
   Summary: is_standard_layout incorrect for colliding member and
base class
   Product: gcc
   Version: 13.1.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

The following compiles on GCC 13.1.0 when it should not:

struct X { };
struct Y {
X x;
};
struct Z : X {
Y y;
};
static_assert(!__is_standard_layout(Z));

By [class.prop]/3.7, rule 3.7.2 makes M(Z) = { Y } union M(Y).  Applying 3.7.2
recursively results in M(Y) = { X } union M(X).  By rule 3.7.1, M(X) = { }.  So
M(Z) = { Y, X }.  By rule 3.7, Z is not standard-layout, because Z's base class
X is an element of M(Z) = { Y, X }.

https://gcc.godbolt.org/z/oWhc8vs6z

[Bug c++/94554] spurious -Waddress warning within "if constexpr" function-null compares

2020-04-10 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94554

--- Comment #2 from Melissa  ---
Templates that take an optional function pointer as a template parameter.  It
lets you have templates that change behavior if a null function pointer is
passed.

[Bug c++/94554] New: spurious -Waddress warning within "if constexpr" function-null compares

2020-04-10 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94554

Bug ID: 94554
   Summary: spurious -Waddress warning within "if constexpr"
function-null compares
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

The following with -std=c++17 -Waddress:

int meow() { return 1; }
void kitty(int);
template 
void test() {
if constexpr (F) {
kitty(F());
} else {
kitty(2);
}
}
template void test();
template void test();

gives a spurious/pointless warning:

: In instantiation of 'void test() [with int (* F)() = meow]':
:12:26:   required from here
:5:5: warning: the address of 'int meow()' will never be NULL
[-Waddress]
5 | if constexpr (F) {
  | ^~

The warning should be suppressed in "if constexpr" contexts, because of course
it's going to be always true or always false.

Clang errors on this case, so it's possible that my code is invalid: Is it
legal to compare a function pointer against null in a constant-expression?

[Bug c++/84581] New: GCC expects "override" keyword in incorrect grammar position

2018-02-26 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84581

Bug ID: 84581
   Summary: GCC expects "override" keyword in incorrect grammar
position
   Product: gcc
   Version: 7.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

GCC expects the "override" keyword in an incorrect position in the C++ grammar:

#define MEOW 256
struct Base {
virtual const char (() const)[MEOW] = 0;
};
struct Derived : public Base {
// GCC requires this incorrect syntax...
virtual const char (() const override)[MEOW];
// ...but the below is the correct syntax, which GCC rejects.
virtual const char (() const)[MEOW] override;
};

In the C++ Standard, "override" is a virt-specifier in a virt-specifier-seq. 
virt-specifier-seq optionally goes after the declarator.  After the optional
virt-specifier-seq goes the optional pure-specifier.


Possibly related bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64794  (I
don't know whether "-> override" is sensible; just linking this in case that
bug's reporter is correct.)

[Bug c++/84415] New: Using __m128 as a template parameter causes warnings

2018-02-15 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84415

Bug ID: 84415
   Summary: Using __m128 as a template parameter causes warnings
   Product: gcc
   Version: 7.3.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

Attempting to use one of the intrinsic x86 vector types like __m128 causes a
warning:

:9:30: warning: ignoring attributes on template argument '__m128 {aka
__vector(4) float}' [-Wignored-attributes]
 __m128 Purr(const Meow<__m128> )
 ^
This is really annoying in warnings-as-errors mode.

This doesn't happen for uint64x2_t on ARM or ARM64.


#include 
template 
struct Meow
{
T x;
};
__m128 Purr(const Meow<__m128> )
{
return m.x;
}

[Bug tree-optimization/82224] Strict-aliasing not noticing valid aliasing of two unions with active members

2017-09-25 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82224

--- Comment #5 from Melissa  ---
This originated from a Stack Overflow post "supercat" made (I'm the "Myria"
there).

https://stackoverflow.com/questions/46205744/is-this-use-of-unions-strictly-conforming/

[Bug c/82224] Strict-aliasing not noticing valid aliasing of two unions with active members

2017-09-15 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82224

--- Comment #3 from Melissa  ---
(In reply to Andrew Pinski from comment #1)
> See PR 14319 which I think this is a dup of.

PR 14319 refers to a case in which you are allowed to read the common prefix of
a structure when the structure is not the active member of the union.

In this report, however, it is never the case that an inactive member is
accessed.  Instead, it appears that GCC isn't aware of aliasing of two pointers
when it comes to tracking which is the active member.

Melissa

[Bug c/82224] New: Strict-aliasing not noticing valid aliasing of two unions with active members

2017-09-15 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82224

Bug ID: 82224
   Summary: Strict-aliasing not noticing valid aliasing of two
unions with active members
   Product: gcc
   Version: unknown
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

Consider the following C/C++ code with -O3 -fstrict-aliasing:

struct s1 {unsigned short x;};
struct s2 {unsigned short x;};
union s1s2 { struct s1 v1; struct s2 v2; };

static int read_s1x(struct s1 *p) { return p->x; }
static void write_s2x(struct s2 *p, int v) { p->x=v;}

int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3)
{
  if (read_s1x(>v1))
  {
unsigned short temp;
temp = p3->v1.x;
p3->v2.x = temp;
write_s2x(>v2,1234);
temp = p3->v2.x;
p3->v1.x = temp;
  }
  return read_s1x(>v1);
}
int test2(int x)
{
  union s1s2 q[2];
  q->v1.x = 4321;
  return test(q,q+x,q+x);
}
#include 
int main(void)
{
  printf("%d\n",test2(0));
}

GCC (and Clang) generate code that outputs 4321 instead of the expected 1234.

I don't really understand things in terms of the C standard, but in terms of
the C++ standard, it seems as if GCC and Clang are incorrect, and this code is
well-defined.  (The output is 4321 in both C and C++ mode.)

According to [class.union]/5 in the C++17 draft N4659, the assignment
expression "p3->v2.x = temp;" changes the active member of the union.  It's
done through a union member access expression.  Thus the pointer >v2 is
valid here.

Even if I switch this to "p3->v2 = { x };", avoiding the nested case, the
problem still happens.

Even if I explicitly change the active member of the union with placement new
as "new() s2;", the problem still happens.

Is it possible that Clang doesn't see the possibility that p2 and p3 point to
the same object?

Clang cross-reference: https://bugs.llvm.org/show_bug.cgi?id=34632

[Bug target/79155] New: Typo in cpuid.h comment

2017-01-19 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79155

Bug ID: 79155
   Summary: Typo in cpuid.h comment
   Product: gcc
   Version: 7.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: target
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

x86's gcc/config/i386/cpuid.h contains the following comment:

/* Return highest supported input value for cpuid instruction.  ext can
   be either 0x0 or 0x800 to return highest supported value for
   basic or extended cpuid information.  Function returns 0 if cpuid
   is not supported or whatever cpuid returns in eax register.  If sig
   pointer is non-null, then first four bytes of the signature
   (as found in ebx register) are returned in location pointed by sig.  */

The second hex constant should be 0x8000, with one more zero.  The
implementation of __get_cpuid below uses 0x8000 correctly.

[Bug c++/55004] [meta-bug] constexpr issues

2016-10-12 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55004
Bug 55004 depends on bug 67333, which changed state.

Bug 67333 Summary: [C++11][constexpr] constexpr functions incorrectly prohibit 
taking references to volatile types
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67333

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

[Bug c++/67333] [C++11][constexpr] constexpr functions incorrectly prohibit taking references to volatile types

2016-10-12 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67333

Melissa  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #3 from Melissa  ---
Seems to have been fixed sometime between 6.0 and 6.1.

[Bug sanitizer/77891] New: Signed overflow sanitizer doesn't catch multiplication overflows due to promotion

2016-10-06 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77891

Bug ID: 77891
   Summary: Signed overflow sanitizer doesn't catch multiplication
overflows due to promotion
   Product: gcc
   Version: 6.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: sanitizer
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
jakub at gcc dot gnu.org, kcc at gcc dot gnu.org
  Target Milestone: ---

-fsanitize=signed-integer-overflow doesn't catch multiplication overflows that
occur in signed types due to promotion rules.  This can happen when you use an
unsigned type that is exactly half the width of "signed int".  That's usually
"unsigned short".

The following should generate two runtime errors when compiled with
-fsanitize=signed-integer-overflow, but instead only one error occurs:

#include 

int main()
{
std::printf("unsigned short\n");
std::fflush(stdout);
unsigned short x = 65535;
x *= x;

std::printf("signed int\n");
std::fflush(stdout);
signed int y = 65535;
y *= y;

return 0;
}

myria@machine:~/tests$ g++ -m64 -std=gnu++11 -Wstrict-overflow -ftrapv
-fstrict-overflow -fsanitize=signed-integer-overflow overflow.cpp -lpthread
-ldl -o overflow64
myria@machine:~/tests$ ./overflow64
unsigned short
signed int
overflow.cpp:13:15: runtime error: signed integer overflow: 65535 * 65535
cannot be represented in type 'int'

Clang does pick up the overflow, though:

myria@machine:~/tests$ clang++-3.8 -m64 -std=gnu++11 -stdlib=libc++
-fsanitize=signed-integer-overflow overflow.cpp -o overflow64
myria@machine:~/tests$ ./overflow64
unsigned short
overflow.cpp:8:11: runtime error: signed integer overflow: 65535 * 65535 cannot
be represented in type 'int'
signed int
overflow.cpp:13:11: runtime error: signed integer overflow: 65535 * 65535
cannot be represented in type 'int'

[Bug c/65892] gcc fails to implement N685 aliasing of union members

2015-09-08 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892

Melissa  changed:

   What|Removed |Added

 CC||myriachan at gmail dot com

--- Comment #12 from Melissa  ---
This is broken in C++ as well, and in C++, the rules are much more clear that
GCC isn't following them.

Quoting the C++ Standard, revision 4296 (post-C++14?):

16. The "common initial sequence" of two standard-layout struct (Clause 9)
types is the longest sequence of non-static data members and bit-fields in
declaration order, starting with the first such entity in each of the structs,
such that the corresponding entries have layout-compatible types and either
neither entity is a bit-field or both are bit-fields with the same width.

19. In a standard-layout union with an active member (9.5) of struct type T1,
it is permitted to read a non-static data member m of another union member of
struct type T2 provided m is part of the common initial sequence of T1 and T2.


A C++ conversion of the original example is below.  I asked about the word
"read" on the C++ Standard Discussion (std-discussion) mailing list, because it
probably should also allow writing if it allows reads.  As a result, I modified
the below to only *read* in an aliasing way, to fully comply with the written
word of the Standard.


#include 

struct t1 { int m; };
struct t2 { int m; };

union U {
t1 s1;
t2 s2;
};

int f (t1 *p1, t2 *p2)
{
// union U visible here, p1->m and p2->m may alias
// p1 is the active member; read from p2 per [class.mem]/19.

if (p2->m < 0)
p1->m = -p1->m;

return p2->m;
}

int main (void)
{
union U u = { { -1 } };

int n = f (, );

assert (1 == n);

return 0;
}


[Bug c/65892] gcc fails to implement N685 aliasing of union members

2015-09-08 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65892

--- Comment #13 from Melissa  ---
As for a reason why this should be allowed, all I need is to do is mention
struct sockaddr.


[Bug c++/49171] [C++0x][constexpr] Constant expressions support reinterpret_cast

2015-08-23 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49171

Melissa myriachan at gmail dot com changed:

   What|Removed |Added

 CC||myriachan at gmail dot com

--- Comment #12 from Melissa myriachan at gmail dot com ---
(In reply to Kai Tietz from comment #11)
 Fixed with delayed-folding for C++.  Therefore mine.

Why fix it?  The Standard doesn't allow it, but it's still useful.  For
example, std::numeric_limitsfloat::infinity() cannot be implemented without
it or compiler magic (e.g. __builtin_huge_valf in the current libstdc++).

Melissa


[Bug c++/67333] New: [C++11][constexpr] constexpr functions incorrectly prohibit taking references to volatile types

2015-08-23 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67333

Bug ID: 67333
   Summary: [C++11][constexpr] constexpr functions incorrectly
prohibit taking references to volatile types
   Product: gcc
   Version: 5.2.1
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

GCC 4.7.3 (at least) through GCC 6.0 reject the following due to meow has
side-effects:

#include cstddef
#include type_traits

template typename T, std::size_t S
constexpr std::size_t lengthof(const volatile T ()[S])
{
return S;
}

int main()
{
volatile int meow[4];
static_castvoid(meow); // shut up warning
return static_castint(std::integral_constantstd::size_t,
lengthof(meow)::value);
}

I believe that this is legal per [expr.const] in the Standard, because the
volatile parameter is never used in an lvalue-to-rvalue conversion, which is
what [expr.const] disallows in constant-expressions for volatile types.  Clang
versions that understand this code accept it; Visual C++ 2015 does as well.

Someone who replied to my question on the std-discussion mailing list
suggested that this is also technically legal as well:

#include type_traits

constexpr int Test(int x)
{
volatile int v = x;
return x;
}

int main()
{
return std::integral_constantint, Test(2)::value;
}

GCC also rejects this, but Clang accepts this as well.  Any attempt to read v
will fail, though, so Clang is enforcing the rule.  I'm not on my Windows
machine as I write this, so I can't check MSVC.


[Bug inline-asm/67317] New: [x86] Silly code generation for _addcarry_u32/_addcarry_u64

2015-08-21 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67317

Bug ID: 67317
   Summary: [x86] Silly code generation for
_addcarry_u32/_addcarry_u64
   Product: gcc
   Version: 5.2.0
Status: UNCONFIRMED
  Severity: minor
  Priority: P3
 Component: inline-asm
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Target Milestone: ---

x86 intrinsics _addcarry_u32 and _addcarry_u64 generate silly code.  For
example, the following function to get the result of a 64-bit addition (the XOR
is to the output clearer):

u64 testcarry(u64 a, u64 b, u64 c, u64 d)
{
u64 result0, result1;
_addcarry_u64(_addcarry_u64(0, a, c, result0), b, d,
result1);
return result0 ^ result1;
}

This is the code generated with -O1, -O2 and -O3:

xor r8d, r8d
add r8b, -1
adc rdx, rdi
setcr8b
mov rax, rdx
add r8b, -1
adc rcx, rsi
xor rax, rcx
ret

The first sillyness is that _addcarry_u64 does not optimize a compile-time
constant 0 being the first carry parameter.  Instead of adc, it should just
use add.

The second sillyness is with the use of r8b to store the carry flag, then using
add r8b, -1 to put the result back into carry.

Instead, the code should be something like this:

add rdx, rdi
mov rax, rdx
adc rcx, rsi
xor rax, rcx
ret

Naturally, for something this simple, I'd use unsigned __int128, but this came
up in large number math.


[Bug c++/49604] forward-declared enum's elements in class scope gets default access (class vs struct)

2014-10-16 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49604

Melissa myriachan at gmail dot com changed:

   What|Removed |Added

 CC||myriachan at gmail dot com

--- Comment #3 from Melissa myriachan at gmail dot com ---
Happens for me on 5.0.0 build 2014/10/15 (via wandbox) through 4.6.x - whenever
typed enums were added.

Simpler test case than the original:


class MyTable {
public:
enum Constants : unsigned;
};

enum MyTable::Constants : unsigned {
LENGTH = 12,
};

int main()
{
return MyTable::LENGTH;
}


[Bug c++/61816] New: Member functions of a template class can access private classes without permission

2014-07-15 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61816

Bug ID: 61816
   Summary: Member functions of a template class can access
private classes without permission
   Product: gcc
   Version: 4.9.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: myriachan at gmail dot com
  Host: x86_64-unknown-linux-gnu
Target: x86_64-unknown-linux-gnu
 Build: x86_64-unknown-linux-gnu

There exists a case in which a member function of a forward-declared template
can access a private inner class without permission.  Possible duplicate of bug
41437.


class ClassWithEverythingPrivate {
class InnerClass {
public:
static int InnerFunction() {
return 123;
}
};
};

template typename T class TemplateClass {
public:
static int StaticFunction() {
return ClassWithEverythingPrivate::InnerClass::InnerFunction();
}
};

int main() {
return TemplateClassvoid::StaticFunction();
}


[Bug c++/61015] Stack corruption with templates and pass-by-reference

2014-07-15 Thread myriachan at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61015

Melissa myriachan at gmail dot com changed:

   What|Removed |Added

 CC||myriachan at gmail dot com

--- Comment #1 from Melissa myriachan at gmail dot com ---
Your code is doing something bad - it's retaining a pointer to a temporary
object across a function call.

Although pointers to a derived class are convertible to pointers to a parent
class, that is not true for double-pointers.  For example, the following code
is not legal:

struct Base {};
struct Derived : Base {};

int main()
{
// I don't normally use so-called Hungarian notation, but here it's clearer
Derived *pDerived = new Derived();
Derived **ppDerived = pDerived;

// This is legal.
Base *pBase = pDerived;

// This is not legal, and will cause a compiler error.
Base **ppBase = ppDerived;
return 0;
}

So back to your code, the problem is visible in this small part:

templatetypename T
class ArrayRef
{
  private:
const T* data;
ArrayRef( const T oneElt )  // --- important
{
  this-data = oneElt;
  ...
}
};

int main()
{
  SpecialObj specialObj;
  SpecialObj* pSpecialObj = specialObj;
  ArrayRefObj* arrayRef( pSpecialObj );
...
}

The important thing is the const T  parameter.  T is Obj *, not SpecialObj *,
so the constructor takes Obj *const .  (The const ends up on the right side of
the asterisk in this notation when expanding out T.)  References are really
pointers in alternate syntax, and just like pointers, it is not legal to have a
double-pointer conversion from derived to base.  Just like how SpecialObj **
can't be assigned to type Obj *const *, it's also the case that SpecialObj *
can't be bound to Obj *const .

But why does it compile when the double-pointer case didn't?  It's because
const references have another property: they also take temporaries.  If an
object cannot be bound as a const lvalue to the const reference, the compiler
will instead try to create a temporary using an implicit conversion,
constructor call, or similar, then bind the temporary to the const reference.

Here, the temporary it can create is of type Obj *.  And sure enough,
SpecialObj * can be implicitly converted to Obj *.  So the compiler is going to
create a temporary Obj * on the stack containing a copy of the SpecialObj *
cast to Obj *, then pass *that* to to the ArrayRefT constructor.  Then you
save a pointer to the passed const Obj * inside the ArrayRefT constructor. 
References are really just pointers behind the scenes - and you just saved a
pointer to a temporary object.  Now your ArrayRef class has a pointer to an
arbitrary location in the caller's stack.

I'm going to guess that the compilers that don't crash are actually not
crashing because of the optimizer.  The inlining of the optimizer may actually
cause the temporary to remain in the current stack frame, possibly preventing
the pointer from corrupting anything.  It's when the pointer stored in
ArrayRefT points to a temporary whose memory was freed and reused that you
have a problem.