| Summary: | std::optional use: "Conditional jump or move depends on uninitialised value(s)" (clang) aarch64 | ||
|---|---|---|---|
| Product: | [Developer tools] valgrind | Reporter: | m <kde.sigfw> |
| Component: | memcheck | Assignee: | Paul Floyd <pjfloyd> |
| Status: | REPORTED --- | ||
| Severity: | normal | CC: | mark, pjfloyd |
| Priority: | NOR | ||
| Version First Reported In: | 3.22.0 | ||
| Target Milestone: | --- | ||
| Platform: | Other | ||
| OS: | Linux | ||
| Latest Commit: | Version Fixed/Implemented In: | ||
| Sentry Crash Report: | |||
|
Description
m
2024-04-09 13:49:47 UTC
Forgot to mention that O1 can be used instead of O2 as a workaround, or clang-16 or earlier should also work as a workaround. With debuginfo it might be OK to suppress this. I am unable to replicate this with either clang version 17.0.6 or 18.1.2, not with -O2 or -O1. (In reply to Mark Wielaard from comment #3) > I am unable to replicate this with either clang version 17.0.6 or 18.1.2, > not with -O2 or -O1. On x86_64. Missed that the original report was against arm64 (sorry). I can reproduce this on FreBSD 14 arm64 with clang++ 18.0.0 ==14165== Conditional jump or move depends on uninitialised value(s) ==14165== at 0x210A30: ~__optional_destruct_base (optional:247) ==14165== by 0x210A30: dummy_or_default() (bug485276.cpp:23) ==14165== by 0x210A9F: main (bug485276.cpp:28) │ 244 _LIBCPP_INLINE_VISIBILITY
│ 245 _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__optional_destruct_base()
│ 246 {
│ > 247 if (__engaged_)
│ 248 __val_.~value_type();
│ 249 }
Not sure what is happening. The error occurs as above, but it's not just __engaged_ that is not initialized, this points to an uninitialized object.
(gdb) mc xb &__engaged_ sizeof(__engaged_)
ff
0x1FFFFFF8F0: 0x60
(gdb) mc xb this sizeof(*this)
00 ff ff ff ff ff ff ff
0x1FFFFFF8E0: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ff ff ff ff ff ff ff ff
0x1FFFFFF8E8: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
ff ff ff ff ff ff ff ff
0x1FFFFFF8F0: 0x60 0xf9 0xff 0xff 0x1f 0x00 0x00 0x00
type = struct std::__1::__optional_destruct_base<dummy, false> [with _Tp = dummy] {
union {
char __null_state_;
value_type __val_;
};
bool __engaged_;
public:
~__optional_destruct_base(void);
__optional_destruct_base(void);
void reset(void);
typedef _Tp value_type;
}
'this' points to memory on the stack which is why it's safe to dereference.
I'm not familiar with the code, but as I understand it, this is the key function:
static Bool stmt_is_guardable ( const IRStmt* st )
{
switch (st->tag) {
// These are easily guarded.
case Ist_NoOp:
case Ist_IMark:
case Ist_Put:
case Ist_PutI:
return True;
// These are definitely not guardable, or at least it's way too much
// hassle to do so.
case Ist_CAS:
case Ist_LLSC:
case Ist_MBE:
return False;
// These could be guarded, with some effort, if really needed, but
// currently aren't guardable.
case Ist_LoadG:
case Ist_Store:
case Ist_StoreG:
case Ist_Exit:
case Ist_Dirty:
return False;
// This is probably guardable, but it depends on the RHS of the
// assignment.
case Ist_WrTmp:
return expr_is_guardable(st->Ist.WrTmp.data);
default:
vex_printf("\n"); ppIRStmt(st); vex_printf("\n");
vpanic("stmt_is_guardable: unhandled stmt");
}
}
|