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: | 3.22.0 | ||
Target Milestone: | --- | ||
Platform: | Other | ||
OS: | Linux | ||
Latest Commit: | Version Fixed 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"); } } |