[Bug c++/116534] New: [14 regression] internal compiler error with comparison of pointers calculated with array offset
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116534 Bug ID: 116534 Summary: [14 regression] internal compiler error with comparison of pointers calculated with array offset Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: john at drouhard dot dev Target Milestone: --- The following produces an internal compiler when compiled with -Wall starting with gcc 14: $ cat test.cpp template class Test { void foo(unsigned x, unsigned y) { bool test = &a[x] == &b[y]; } unsigned *a; unsigned *b; }; $ g++ -Wall ./test.cpp ./test.cpp: In member function 'void Test::foo(unsigned int, unsigned int)': ./test.cpp:4:34: internal compiler error: Segmentation fault 4 | bool test = &a[x] == &b[y]; | ^ Please submit a full bug report, with preprocessed source (by using -freport-bug). See <https://gcc.gnu.org/bugs/> for instructions.
[Bug libstdc++/111050] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111050 John Drouhard changed: What|Removed |Added CC||john at drouhard dot dev --- Comment #10 from John Drouhard --- (In reply to frs.dumont from comment #9) > To be honest before that report I thought that preserving abi was just a > matter of preserving memory layout of types. I had no idea that member > methods mattered ! (I was the original reporter of this to TC) I think the specific issue here is that the member function `_M_valptr()` returns the address of the storage data member, and that _function_ is used in a construct call elsewhere to point to the address where a new object should be placed. It returns the address based on the offset from the beginning of the object which changed when the base class (which had its own data members) was removed. So, if the function isn't inlined, the symbol that's actually loaded by the dynamic linker during runtime will return a potentially bogus address for that data member if the definition of that function came from a library compiled with the other version.
[Bug libstdc++/109111] Definition of repeat_view::_Iterator has wrong template-head
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109111 --- Comment #1 from John Drouhard --- https://godbolt.org/z/csozden6e example of gcc not diagnosing mismatched requires clauses (and clang correctly doing so).
[Bug c++/101118] coroutines: unexpected ODR warning for coroutine frame type in LTO builds
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101118 --- Comment #5 from John Drouhard --- Has there been any progress toward resolution for this? We've been trying to use coroutines in our project but we require LTO for performance reasons, so this is holding us back.
[Bug c++/93018] Zero initialization not occurring for empty struct in member union when converting constructor is used with -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93018 --- Comment #3 from John Drouhard --- I don't think this is a matter of object lifetime. Passing -fnolifetime-dse or -flifetime-dse=1 does not change the generated assembly here at all. As a user of the functions baz1 and baz2, I would expect the returned object to have identical object representations. Bar's default constructor as well as its user-defined constructor with the null_t argument should produce identical objects here. Even if the copy constructor is used to copy from a temporary object during the return from baz1/baz2, union class types' default copy constructors copy the object representations (as if memmove is used), so we should still be seeing a zero-initialized "foo" member. The assembly generated with -O2, for reference: baz1(long long): xorl%eax, %eax movl$0, %edx testq %rdi, %rdi cmovg %rdi, %rdx setg%al ret baz2(long long): xorl%eax, %eax testq %rdi, %rdi jle .L7 movb$1, %al movq%rdi, %rdx .L7: ret %rax is the bool member of bar, %rdx is the union member. baz2 is simply not storing anything in %rdx, so the caller receives an uninitialized value (instead of zero-initialization) for the union "foo" member. If I write the following program: int main() { Bar obj = baz2(0); printf("%08x\n", *((long long*)&obj.foo)); return 0; } Random garbage is printed out. If I change it to use baz1 instead, 0 is correctly printed. If I change the optimization level to -O3, 0 is correctly printed. If I change the implementation of baz2(long long) to unconditionally return the null sentinel object, 0 is correctly printed. "obj" is also definitely still alive at this point in the program, so object lifetime is not the problem. It seems to only be uninitialized when using the converting constructor in the return statement, using -O2 optimization, and there is another path in the function that returns an object where the active union member is not the empty struct and is initialized.
[Bug c++/93018] Zero initialization not occurring for empty struct in member union when converting constructor is used with -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93018 --- Comment #1 from John Drouhard --- I forgot to mention that changing the optimization level to -O3 appears to "fix" baz2, and it correctly zero-initializes the empty struct in the union.
[Bug c++/92964] order of base class members generates vastly different code
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92964 --- Comment #1 from John Drouhard --- I opened a separate bug report for the second issue I discussed in this one. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93018
[Bug c++/93018] New: Zero initialization not occurring for empty struct in member union when converting constructor is used with -O2
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93018 Bug ID: 93018 Summary: Zero initialization not occurring for empty struct in member union when converting constructor is used with -O2 Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: john at drouhard dot dev Target Milestone: --- Created attachment 47528 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47528&action=edit reproducible c++ source When a converting constructor is used to return a struct that contains a bool and a union with an instance of an empty struct as a member, the padding byte for that empty struct member is not zero initialized. See the attached reproducible. I've reproduced this on gcc 8.1-8.3, 9.2, and trunk (using godbolt.org). Here's the godbolt link: https://godbolt.org/z/voL7B5 Compile with -std=c++17 -O2 -DEMPTY (which will use an empty struct in the union). Omit -DEMPTY to see that naming the byte (thus making it part of the value representation instead of the object representation) causes it to correctly zero initialize. It also correctly zero initializes if the function that returns the struct does so by returning a value-initialized Bar (baz1). In baz2, a converting constructor from a null_t to Bar is used, though the same behavior should occur as in baz1. I believe zero initialization is required by the standard for the byte in the empty struct. From the draft standard as of 2017-11-27: = 6.6.2 paragraph 7: Unless it is a bit-field (12.2.4), a most derived object shall have a nonzero size and shall occupy one or more bytes of storage. Base class subobjects may have zero size. An object of trivially copyable or standard-layout type (6.7) shall occupy contiguous bytes of storage. 6.7 paragraph 4: The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. Bits in the object representation that are not part of the value representation are padding bits. 11.6 paragraph 6: To zero-initialize an object or reference of type T means: (6.2) — if T is a (possibly cv-qualified) non-union class type, its padding bits (6.7) are initialized to zero bits and each non-static data member, each non-virtual base class subobject, and, if the object is not a base class subobject, each virtual base class subobject is zero-initialized; (6.3) — if T is a (possibly cv-qualified) union type, its padding bits (6.7) are initialized to zero bits and the object’s first non-static named data member is zero-initialized; 11.6 paragraph 8: To value-initialize an object of type T means: (8.1) — if T is a (possibly cv-qualified) class type (Clause 12) with either no default constructor (15.1) or a default constructor that is user-provided or deleted, then the object is default-initialized; (8.2) — if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized; (8.3) — if T is an array type, then each element is value-initialized; (8.4) — otherwise, the object is zero-initialized. = The empty "e" member in the "Foo" union is being value-initialized in the member initializer list of the default constructor of Foo. Value-initialization for an empty struct should cause zero-initialization of the padding bytes, which is the single byte of the object representation for instances of an empty struct. baz1 seems to do this correctly, baz2 does not.
[Bug c++/92964] New: order of base class members generates vastly different code
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92964 Bug ID: 92964 Summary: order of base class members generates vastly different code Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: john at drouhard dot dev Target Milestone: --- Created attachment 47510 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=47510&action=edit reproducible c++ source I'm new at submitting bug reports, sorry if this one is invalid.D I have attached a repro file that actually exhibits what I believe to be two issues, but I'm unsure of the second. If I need to open a second report for it (or if it's really not a problem) just let me know. I've reproduced this behavior on gcc 8.3, gcc 9.2, and gcc trunk. Godbolt link if interested: https://godbolt.org/z/F756Pe Anyway, looking at the generated assembly when compiling the program with -std=c++17 -O2 (and -O3) seems to indicate a missed optimization of some kind. bar1() and bar3() are equivalent, other than the order of the union and the bool in the base storage class. I believe gcc should be able to generate basically the same assembly as well (other than swapping %rax/%rdx), but bar3 utilizes the stack, even using SIMD instructions for the false branch. bar1 doesn't do this. clang generates equivalent code for bar1/bar3. I'm assuming it has something to do with alignment, but what's strange is that if the intermediary Payload class is bypassed by using a PayloadBase directly in Foo<>, bar1 and bar3 are generated (almost) equivalently as expected (no SIMD instructions or stack usage). The other issue (please let me know if I should just open another report or if this is expected), is the difference between bar1/bar2 and bar3/bar4. They only differ in how they return the Foo<> object. bar1/bar3 return a default constructed Foo<>, but bar2/bar4 return a sentinel and rely on converting to Foo<> using the user-defined constructor. Generated assembly for these pairs of functions are very different (at least at -O2 optimization). With the -O2 level optimization, bar2 does not set %rdx in the false branch (bar1 does). clang sets it in both. I realize it's not strictly necessary to ensure that a value is returned in %rdx since the empty union member is the one being initialized, but bar1 takes care to make sure it's set to 0 (as does clang for both). Bumping the optimization level up to -O3 actually causes bar2 to ensure both are set to 0 explicitly. bar3 and bar4, however, both intentionally populate %rax with uninitialized junk from the stack in the false branch (both -O2 and -O3), though it's clearer in bar4 since it doesn't use SIMD instructions there (related to the first point?) If initializing %rax isn't necessary, why does it move memory from the uninitialized stack into the return register at all? I apologize if this is not well-thought-out or if there's something obvious I'm missing. Let me know if you need me to provide any more information.