[Bug c++/109795] New: is_standard_layout incorrect for colliding member and base class
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
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
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
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.