[Bug target/105932] New: Small structures returned incorrectly in i386 Microsoft ABI
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105932 Bug ID: 105932 Summary: Small structures returned incorrectly in i386 Microsoft ABI Product: gcc Version: 12.1.0 Status: UNCONFIRMED Keywords: ABI, wrong-code Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Consider this C code: struct foo { int x, y; }; extern int x, y; struct foo f(void) { struct foo rv; rv.x = x; rv.y = y; return rv; } When compiled with "-O2 -m32 -mabi=ms", it compiles to this: f: movdx, %xmm0 movl4(%esp), %eax movdy, %xmm1 punpckldq %xmm1, %xmm0 movq%xmm0, (%eax) ret Which expects to be passed a hidden parameter to hold the address of the return value. But in the i386 Microsoft ABI, that's not how returns work for POD types that are 64 bits or smaller. Here's what it should compile to instead: f: movdx, %eax movdy, %edx ret
[Bug c/105875] New: Toggling an atomic_bool is inefficient
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105875 Bug ID: 105875 Summary: Toggling an atomic_bool is inefficient Product: gcc Version: 12.1.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Target: x86_64-pc-linux-gnu Consider this C code: #include atomic_bool b; atomic_char c; _Bool b2; void f1(void) { b ^= 1; } void f2(void) { c ^= 1; } void f3(void) { b2 ^= 1; } At -O3, those functions compile into this: f1: movzbl b(%rip), %eax .L5: movb%al, -1(%rsp) xorl$1, %eax movl%eax, %edx movzbl -1(%rsp), %eax lock cmpxchgb %dl, b(%rip) jne .L5 ret f2: lock xorb $1, c(%rip) ret f3: xorb$1, b2(%rip) ret The code generated for f1 is inefficient. It should have just done a "lock xorb $1, b(%rip)".
[Bug c++/103091] New: Can't jump into scope of a variable with a nontrivial destructor in C++20
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103091 Bug ID: 103091 Summary: Can't jump into scope of a variable with a nontrivial destructor in C++20 Product: gcc Version: 11.2.1 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- The C++17 standard says "A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer (11.6)." The C++20 standard says "A program that jumps from a point where a variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has vacuous initialization (6.7.3)." and "A variable is said to have vacuous initialization if it is default-initialized and, if it is of class type or a (possibly multi-dimensional) array thereof, that class type has a trivial default constructor." Note that the C++17 standard mentions a trivial destructor here, but the C++20 standard does not. Now consider this code: struct MyStruct { ~MyStruct() {} }; void foo() { goto x; MyStruct s; x: return; } It's ill-formed in C++17, but fine in C++20. However, we currently reject this program even with -std=c++20.
[Bug debug/102442] Incorrect debug info for C89-style function parameter
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102442 Joseph C. Sible changed: What|Removed |Added CC||josephcsible at gmail dot com --- Comment #1 from Joseph C. Sible --- I wonder if this is related to fx actually being a float(double) and not a float(float) as it appears to be.
[Bug c++/101465] New: Poorly worded error from a call to a pointer-to-member function not wrapped in parentheses
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101465 Bug ID: 101465 Summary: Poorly worded error from a call to a pointer-to-member function not wrapped in parentheses Product: gcc Version: 11.1.0 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Consider this C++ code: struct foo *x; void (foo::*myfuncptr)(); void f() { x->*myfuncptr(); } This fails to compile, as it should. The problem is that the error I get says I "must use '.*' or '->*' to call pointer-to-member function", even though I'm already using '->*'. The actual change I need to make is to add parentheses, like this: "(x->*myfuncptr)();" We should make the error say this instead.
[Bug c/101432] New: NULL dereferences aren't assumed to be unreachable even with -fdelete-null-pointer-checks -fno-isolate-erroneous-paths-dereference
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101432 Bug ID: 101432 Summary: NULL dereferences aren't assumed to be unreachable even with -fdelete-null-pointer-checks -fno-isolate-erroneous-paths-dereference Product: gcc Version: 11.1.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Target: x86_64-linux-gnu Consider this C code: #include int f(_Bool x) { if(x) { int *null = NULL; return *null; } else { return 42; } } I want this assembly: f: movl$42, %eax ret But even with -O3 -fdelete-null-pointer-checks -fno-isolate-erroneous-paths-dereference, I get this assembly: f: movl$42, %eax testb %dil, %dil je .L1 movl0, %eax .L1: ret
[Bug c/101358] New: Warn when saving a pointer to an object with temporary lifetime
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101358 Bug ID: 101358 Summary: Warn when saving a pointer to an object with temporary lifetime Product: gcc Version: 12.0 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Consider this C code: typedef struct { int x[1]; } foo; foo f(void); int g(void) { int *p = f().x; return *p; } The g() function is always UB, since the return value of f() has temporary lifetime, so doing "return *p;" is dereferencing a pointer to an object whose lifetime has ended. (This is the case both before and after C11's change to temporary lifetime.) Since it's obvious at compile time that p can never be used safely, we should have a warning for it, similar to how we have -Wreturn-local-addr to catch mistakes like this function: int *h(void) { int x; return &x; }
[Bug middle-end/100861] False positive -Wmismatched-new-delete with destroying operator delete
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861 --- Comment #2 from Joseph C. Sible --- Wait, if it's just checking whether the calls to operator new and operator delete match up, then why does adding "virtual ~Widget() {}" make the warning go away?
[Bug c++/100861] New: False positive -Wmismatched-new-delete with destroying operator delete
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100861 Bug ID: 100861 Summary: False positive -Wmismatched-new-delete with destroying operator delete Product: gcc Version: 12.0 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Currently, code like "Base *b = new Derived; delete b;" gives a -Wmismatched-new-delete warning, unless Base has a virtual destructor. One of the use cases for C++20's destroying operator delete is to make this safe without needing a virtual destructor, so this warning should be suppressed if Base has a destroying operator delete. Here's a modified version of the code at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0722r1.html that will unnecessarily cause this warning (compile with -std=c++20 -Wall): #include enum class WidgetKind { Grommet, Wingnut }; struct Widget { const WidgetKind Kind : 4; unsigned OtherThings : 28; Widget(WidgetKind k) : Kind(k) {} void operator delete(Widget *, std::destroying_delete_t); }; struct Grommet : Widget { Grommet() : Widget(WidgetKind::Grommet) {} }; struct Wingnut : Widget { Wingnut() : Widget(WidgetKind::Wingnut) {} }; void Widget::operator delete(Widget *widget, std::destroying_delete_t) { switch (widget->Kind) { case WidgetKind::Grommet: static_cast(widget)->~Grommet(); ::operator delete(widget, sizeof(Grommet)); return; case WidgetKind::Wingnut: static_cast(widget)->~Wingnut(); ::operator delete(widget, sizeof(Wingnut)); return; } } int main() { Widget *widget = new Grommet; delete widget; }
[Bug c++/91859] Using destroying delete should not clobber stores to the object
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91859 --- Comment #5 from Joseph C. Sible --- The real problem mentioned in comment 2 still happens as of GCC 11.1. I've narrowed it down somewhat to the optimization flags "-Og -ftree-dse -ftree-pta". Removing any one of those will make it behave again.
[Bug c++/97820] New: VLAs in function declarations fail to compile
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97820 Bug ID: 97820 Summary: VLAs in function declarations fail to compile Product: gcc Version: 10.2.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: josephcsible at gmail dot com Target Milestone: --- Consider these 4 attempts at declaring a function: void f1(int rows, int cols, int arr[rows][cols]); void f2(int rows, int cols, int (*arr)[cols]); void f3(int, int, int [*][*]); void f4(int, int, int (*)[*]); When I compile them with g++, they all have errors: :1:41: error: use of parameter outside function body before ']' token 1 | void f1(int rows, int cols, int arr[rows][cols]); | ^ :1:47: error: use of parameter outside function body before ']' token 1 | void f1(int rows, int cols, int arr[rows][cols]); | ^ :2:44: error: use of parameter outside function body before ']' token 2 | void f2(int rows, int cols, int (*arr)[cols]); |^ :3:25: error: expected primary-expression before ']' token 3 | void f3(int, int, int [*][*]); | ^ :3:28: error: expected primary-expression before ']' token 3 | void f3(int, int, int [*][*]); |^ :4:28: error: expected primary-expression before ']' token 4 | void f4(int, int, int (*)[*]); |^ Since we support VLAs in C++ as an extension, I expected that all of these would work. https://godbolt.org/z/Wca9ra