[Bug c++/93901] New: noexcept specifier on ctor does not work with constexpr variable or expression

2020-02-24 Thread paul.groke at dynatrace dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93901

Bug ID: 93901
   Summary: noexcept specifier on ctor does not work with
constexpr variable or expression
   Product: gcc
   Version: 10.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: paul.groke at dynatrace dot com
  Target Milestone: ---

Seems like with GCC 10, only the literal `true` works as expected in noexcept
specifiers for ctors. Other expressions that evaluate to "true" result in ctors
that test as "noexcept(false)". Noexcept specifiers on functions seem to work
just fine though.
Example:


#include 
#include 

extern void *mem;

constexpr bool YES = true;

struct NoexceptTrueCtor {
NoexceptTrueCtor() noexcept(true);
};
void NoexceptTrueFun() noexcept(true);

struct NoexceptYesCtor {
NoexceptYesCtor() noexcept(YES);
};
void NoexceptYesFun() noexcept(YES);

struct NoexceptOneEqOneCtor {
NoexceptOneEqOneCtor() noexcept(1 == 1);
};
void NoexceptOneEqOneFun() noexcept(1 == 1);

struct NoNoexceptCtor {
NoNoexceptCtor();
};
void NoNoexceptFun();

static_assert(std::is_nothrow_default_constructible::value,
"1"); // OK
static_assert(noexcept(new(mem) NoexceptTrueCtor), "2"); // OK
static_assert(noexcept(NoexceptTrueFun()), "3"); // OK

static_assert(std::is_nothrow_default_constructible::value,
"4"); // fail
static_assert(noexcept(new(mem) NoexceptYesCtor), "5"); // fail
static_assert(noexcept(NoexceptYesFun()), "6"); // OK

static_assert(std::is_nothrow_default_constructible::value,
"7"); // fail
static_assert(noexcept(new(mem) NoexceptOneEqOneCtor), "8"); // fail
static_assert(noexcept(NoexceptOneEqOneFun()), "9"); // OK

static_assert(!std::is_nothrow_default_constructible::value,
"10"); // OK
static_assert(!noexcept(new(mem) NoNoexceptCtor), "11"); // OK
static_assert(!noexcept(NoNoexceptFun()), "12"); // OK


This fails with


:32:71: error: static assertion failed: 4
   32 |
static_assert(std::is_nothrow_default_constructible::value,
"4"); // fail
  |  
^
:33:15: error: static assertion failed: 5
   33 | static_assert(noexcept(new(mem) NoexceptYesCtor), "5"); // fail
  |   ^~
:36:76: error: static assertion failed: 7
   36 |
static_assert(std::is_nothrow_default_constructible::value,
"7"); // fail
  |  
~^
:37:15: error: static assertion failed: 8
   37 | static_assert(noexcept(new(mem) NoexceptOneEqOneCtor), "8"); // fail
  |   ^~~
Compiler returned: 1


Tested with godbolt.org: https://godbolt.org/z/BvXe4K
x86-64, g++ (Compiler-Explorer-Build) 10.0.1 20200223 (experimental)

GCC versions 9.2 and older compile the above code just fine as do Clang, MSVC
and ICC.

[Bug c++/82270] New: incorrect warning [-Wignored-attributes]

2017-09-20 Thread paul.groke at dynatrace dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270

Bug ID: 82270
   Summary: incorrect warning [-Wignored-attributes]
   Product: gcc
   Version: 6.4.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: paul.groke at dynatrace dot com
  Target Milestone: ---

Created attachment 42210
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=42210&action=edit
Reproducer

GCC version 6.4, SPARC 32 and 64 bit
System: Solaris
No command line options, i.e. just
g++ test.cpp

Compiler output is:

test.cpp: In function 'int main()':
test.cpp:19:21: warning: ignoring attributes on template argument 'type {aka
type_fn<8u>}' [-Wignored-attributes]
  return meta_fn::value;
 ^

The following versions also emit the same incorrect warning:
GCC version 6.3, ARM (but not ARM64)
GCC version 6.2.1, MSP430

I haven't been able to reproduce the warning with any x86 compiler though -
i.e. GCC 6.4 on Linux x86 doesn't emit the warning.

If I understand this correctly, the warning is incorrect. The attribute is
attached directly to the type (the struct), and thus must not be "lost" if
using the type as a template argument.

---

The following code also produces the same warning (tested with Boost 1.63,
1.64):

#include 

int main()
{
boost::container::small_vector v;
}

[Bug c++/82270] incorrect warning [-Wignored-attributes]

2017-10-10 Thread paul.groke at dynatrace dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270

--- Comment #2 from Paul Groke  ---
I've contributed a workaround to Boost that avoids the bogus warning when using
boost::container::small_vector:
https://github.com/boostorg/move/pull/14

So if whoever fixes this wants to test with boost::container::small_vector,
he/she should use Boost version <= 1.65.1.

[Bug libstdc++/98376] New: this_thread::sleep_for(short duration) can sleep forever on Linux

2020-12-18 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98376

Bug ID: 98376
   Summary: this_thread::sleep_for(short duration) can sleep
forever on Linux
   Product: gcc
   Version: 11.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: libstdc++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: paul.groke at dynatrace dot com
  Target Milestone: ---

If libstdc++ is configured with _GLIBCXX_USE_NANOSLEEP (which seems to be the
case on most systems), it will use nanosleep in this_thread::sleep_for like
this:

__gthread_time_t __ts =
  {
static_cast(__s.count()),
static_cast(__ns.count())
  };
while (::nanosleep(&__ts, &__ts) == -1 && errno == EINTR)
  { }

However on Linux, such a nanosleep loop can run forever because of a Linux bug
that's documented here:
https://man7.org/linux/man-pages/man2/nanosleep.2.html#BUGS

For this to happen the thread needs to receive signals at a high frequency
which seems to be rather uncommon.

However there's a Go feature called non-cooperative preemption that can trigger
this quite easily, see
https://github.com/golang/proposal/blob/master/design/24543-non-cooperative-preemption.md
https://github.com/golang/go/blob/master/src/runtime/signal_unix.go#L352
https://github.com/golang/go/blob/master/src/runtime/preempt.go#L223

This could lead to problems when on Linux, native code that uses libstdc++ is
called from a Go thread. The Go thread executing this_thread::sleep_for will
loop forever calling nanosleep and the other Go thread that tries to preempt it
will also loop forever, perpetually trying to preempt it.

[Bug libstdc++/98376] this_thread::sleep_for(short duration) can sleep forever on Linux

2020-12-18 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98376

--- Comment #1 from Paul Groke  ---
Sorry, I only realized that using links to master doesn't make much sense after
I had already created the ticket.

Those links should be stable:

https://github.com/golang/proposal/blob/5b63da9579c3b19294be614dcad33e20a9a4ad22/design/24543-non-cooperative-preemption.md
https://github.com/golang/go/blob/go1.15.6/src/runtime/signal_unix.go#L347
https://github.com/golang/go/blob/go1.15.6/src/runtime/preempt.go#L223

[Bug libstdc++/98376] this_thread::sleep_for(short duration) can sleep forever on Linux

2020-12-18 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98376

--- Comment #2 from Paul Groke  ---
I was able to reproduce the problem with the following program (see below). It
won't reproduce well on a loaded machine and you may have to fiddle with the
spin counts to get a successful repro.

I know this is a Linux bug, but since a lot of people are using Linux it might
be worth implementing a workaround in libstdc++.

Output from my machine:

Remaining: 0.02000 - signal count: 0
Remaining: 0.312026100 - signal count: 6322
Remaining: 0.610834500 - signal count: 12729
Remaining: 0.907113100 - signal count: 19096
Remaining: 1.202000100 - signal count: 25452
Remaining: 1.499204500 - signal count: 31842
Remaining: 1.799767600 - signal count: 38277
Remaining: 2.095204700 - signal count: 44636
(...snip...)
Remaining: 86.829101800 - signal count: 1865855
Remaining: 87.126722500 - signal count: 1872251
Remaining: 87.427912300 - signal count: 1878704
Remaining: 87.730148000 - signal count: 1885171
Remaining: 88.029529500 - signal count: 1891599
Remaining: 88.329424200 - signal count: 1898039
Remaining: 88.629499900 - signal count: 1904482
Remaining: 88.926003300 - signal count: 1910861
ERROR: timeout. sleep thread seems hung.

---

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std::chrono_literals;

constexpr auto acq = std::memory_order_acquire;
constexpr auto rlx = std::memory_order_relaxed;

constexpr uint64_t sigHandlerSpin = 10'000;
constexpr uint64_t sigSenderSpin = 100;
constexpr int64_t sleepTimeNs = 20'000'000; // 20ms
constexpr int64_t reportIntervalNs = 200'000'000; // 200ms
constexpr auto timeout = 60s;

thread_local bool tls_isSleepThread{false};
std::atomic s_signalCount{0};
std::atomic s_signalPending{false};

struct timespec makeTs(time_t sec, int64_t nsec) {
struct timespec ts = {};
ts.tv_sec = sec;
ts.tv_nsec = nsec;
return ts;
}

void spinWait(uint64_t spinCount) {
[[maybe_unused]] volatile int32_t dummy = 0;
volatile int32_t divisor = 123456789;
volatile int32_t dividend = 33;
for (uint64_t i = 0; i < spinCount; i++)
dummy = divisor / dividend;
}

void signalHandler(int) {
if (tls_isSleepThread) {
s_signalCount++;
spinWait(sigHandlerSpin);
}
s_signalPending = false;
};

void spinBarrier(std::atomic& barrier) {
barrier--;
while (barrier.load(acq)) {
// wait...
}
}

struct State {
std::atomic startBarrier{3};
std::atomic stop{false};
std::atomic reportGen{0};
std::atomic reportSec{0};
std::atomic reportNsec{0};
};

[[maybe_unused]] void nanosleepThreadFn(State& state) {
tls_isSleepThread = true;
auto sleepTime = makeTs(0, sleepTimeNs);
state.reportSec.store(sleepTime.tv_sec, rlx);
state.reportNsec.store(sleepTime.tv_nsec, rlx);

spinBarrier(state.startBarrier);

while (!state.stop) {
if (::nanosleep(&sleepTime, &sleepTime) != -1)
break;
if (errno != EINTR)
break;

auto gen = state.reportGen.load(acq);
state.reportSec.store(sleepTime.tv_sec, rlx);
state.reportNsec.store(sleepTime.tv_nsec, rlx);
state.reportGen.store(gen + 1);
}

state.stop = true;
}

[[maybe_unused]] void stdSleepThreadFn(State& state) {
tls_isSleepThread = true;
auto sleepTime = 1ns * sleepTimeNs;

spinBarrier(state.startBarrier);
std::this_thread::sleep_for(sleepTime);

state.stop = true;
}

void reportThreadFn(State& state) {
auto const delay = makeTs(0, reportIntervalNs);

spinBarrier(state.startBarrier);
while (!state.stop) {
// try to get consistent snapshot...
int64_t sec;
int64_t nsec;
for (size_t i = 0; i < 10; i++) {
auto const gen = state.reportGen.load(acq);
spinWait(10);
sec = state.reportSec.load(rlx);
nsec = state.reportNsec.load(rlx);
spinWait(10);
auto const gen2 = state.reportGen.load(acq);
if (gen2 == gen)
break;
}

std::cout << "Remaining: " << sec << "."
  << std::setfill('0') << std::setw(9) << nsec
  << " - signal count: " << s_signalCount
  << std::endl;
nanosleep(&delay, nullptr);
}
}

int runTest() {
s_signalCount = 0;
s_signalPending = false;

// install SIGURG handler...
struct sigaction oldSigUrgAction = {};
struct sigaction sigUrgAction = {};
sigUrgAction.sa_handler = signalHandler;
sigaction(SIGURG, &sigUrgAction, &oldSigUrgAction);

auto* const state = new State{};

std::thread sleepThread{[state] { nanosleepThreadFn(*state); }};
std::thread reportThread{[state] { reportThreadFn(*state); }};

auto const sleepThreadHandle = sleepThread.native_handle();

spinBarrier(state->startBarrier);

using Clock = std::chrono::steady_clock;
auto const t0 = Clock::now();

// Ham

[Bug libstdc++/54185] [4.7/4.8 Regression] condition_variable not properly destructed

2022-09-21 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54185

Paul Groke  changed:

   What|Removed |Added

 CC||paul.groke at dynatrace dot com

--- Comment #16 from Paul Groke  ---
(In reply to  Jonathan Wakely)

> It fails reliably on AIX too.

I think that is because of non-conformant behavior of AIX's
pthread_mutex_destroy. It will return EBUSY as long as there are still threads
executing a wait function, even if they're already blocked on re-acquiring the
mutex. If you ignore the error and simply releases/unmap the memory of the CV,
you have a good chance of getting a SIGSEGV in the wait function later (after
it has re-acquired the mutex and presumably proceeds to mark the CV
"non-busy").

In our tests, we get the EBUSY every time if we delete the CV while holding the
mutex on the same thread. The SIGSEGV also reproduces quite well, although for
some reason only with 32 bit builds. (AIX 7.1, oslevel 7100-05-03-1837)

[Bug c++/82270] incorrect warning [-Wignored-attributes]

2021-12-04 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82270

Paul Groke  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|DUPLICATE   |---

--- Comment #4 from Paul Groke  ---
This is not the same as bug 97222.

Bug 97222 is about losing attributes that were introduced by a typedef. This
bug is about getting a bogus warning which says that this happened when:
- The attribute is attached directly to a struct
- The a typedef resolving to the struct is then used as a template argument
- Compiling for SPARC
- The attribute isn't really lost

In what is described in bug 97222 OTOH, the attribute is really lost, because
it was introduced by a typedef and not directly attached to a struct as in this
case.

[Bug c++/109665] New: Incorrect code generation for s390/s390x try-catch (__cxa_begin_catch), causing SIGSEGV

2023-04-28 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109665

Bug ID: 109665
   Summary: Incorrect code generation for s390/s390x try-catch
(__cxa_begin_catch), causing SIGSEGV
   Product: gcc
   Version: 12.2.0
Status: UNCONFIRMED
  Severity: normal
  Priority: P3
 Component: c++
  Assignee: unassigned at gcc dot gnu.org
  Reporter: paul.groke at dynatrace dot com
  Target Milestone: ---

In certain situations, GCC generates incorrect s390x code for calling
`__cxa_begin_catch`. The bogus code contains a `lghi %r2,0` right before
calling `__cxa_begin_catch`. r2 is the register for the first and only argument
of `__cxa_begin_catch`, which is a pointer to some struct related to the
exception. And when called with a nullptr, `__cxa_begin_catch` will crash
(SIGSEGV). s390 (`-m31`) is also affected.

To reproduce, compile the following on Linux/s390x with at least `-O1`:

```
void f2(int, int, int, int, int);

void f1() {
try {
f2(42, 42, 42, 42, 0); // SIGSEGV
} catch (...) {
}
}

```

The resulting code with GCC 12.2.0 is this:

```
f1():
  stmg %r6,%r15,48(%r15)
  lghi %r5,42
  aghi %r15,-160
  lghi %r6,0
  lghi %r4,42
  lghi %r3,42
  lghi %r2,42
  brasl %r14,_Z2f2i@PLT
  lg %r4,272(%r15)
  lmg %r6,%r15,208(%r15)
  br %r4
  lghi %r2,0
  brasl %r14,__cxa_begin_catch@PLT
  lmg %r6,%r15,208(%r15)
  jg __cxa_end_catch@PLT
```

See https://godbolt.org/z/TTYr63oM3

The correct code has an `lgr %r2,%r6` instead of the `lghi %r2,0`.

The bug seems to be dependent on several factors:

- The last thing in the try-catch is a function call with at least 5 parameters
  (Note that I only tested with parameter types that each fit into a general
purpose register though)
- The 5th argument must be a zero constant (0, false, ...)
- The try-catch contains a "catch (...)" handler
- At least `-O1` is used
- The function call is not inlined/no constant propagation happens

I found the bug with GCC 9.5.0 but it also happens with at least 11.2.0, 12.1.0
and 12.2.0 (tested with godbolt.org). I don't have newer GCC versions for s390x
handy, so I didn't test with those.

[Bug target/109665] Incorrect code generation for s390/s390x try-catch (__cxa_begin_catch), causing SIGSEGV

2023-04-28 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109665

--- Comment #2 from Paul Groke  ---
-fno-schedule-insns and/or -fno-schedule-insns2 don't change the instruction
sequence for calling __cxa_begin_catch.

BTW: for compiler versions present there, it's super easy to check this with
godbolt.org. Just enter the compiler switches into the text-field next to the
compiler selection control.

[Bug target/109665] Incorrect code generation for s390/s390x try-catch (__cxa_begin_catch), causing SIGSEGV

2023-04-28 Thread paul.groke at dynatrace dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109665

--- Comment #3 from Paul Groke  ---
Created attachment 54952
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=54952&action=edit
Minimal repro

Added minimal repro