Branch: refs/heads/thaines/Operand_noexcept
Home: https://github.com/dyninst/dyninst
Commit: e2d665663e5d2044478ee7af55d5432cbd69e846
https://github.com/dyninst/dyninst/commit/e2d665663e5d2044478ee7af55d5432cbd69e846
Author: Tim Haines <thaines.astro@xxxxxxxxx>
Date: 2024-01-09 (Tue, 09 Jan 2024)
Changed paths:
M instructionAPI/h/Operand.h
Log Message:
-----------
Fix libstdc++ noexcept requirement for Operand ctor
As you can see below, std::constuct_at is requiring that Operand be
noexcept constructible. I _think_ this is a QoI item in libstdc++.
1. The offending call to std::vector::resize(size_type) at
RoseInsnFactory.C:152 is covered by the note in
(https://en.cppreference.com/w/cpp/container/vector/resize):
In overload (1), if T's move constructor is not noexcept and T is not
CopyInsertable into *this, vector will use the throwing move
constructor. If it throws, the guarantee is waived and the effects
are unspecified.
2. Operand's ctor is _not_ noexcept, but it _is_ CopyInsertable
(https://en.cppreference.com/w/cpp/named_req/CopyInsertable), so we
get the second part and encounter UB.
3. A note on CopyInsertable says that a CopyInsertable must use
std::construct_at (see cppref page above), and std::construct_at has
a caveat of behavior (https://en.cppreference.com/w/cpp/memory/construct_at):
Specialization of this function template participates in overload
resolution only if
::new(std::declval<void*>()) T(std::declval<Args>()...) is well-formed
in an unevaluated context.
>From (1), we would get UB in constexpr context, but
RoseInsnFactory.C:152 isn't in a constexpr context... We have to use
std::construct_at by (2). I think the QoI issue is that (3) gets
enforced even though we aren't in a constexpr context.
In file included from /usr/include/c++/12/bits/char_traits.h:46,
from /usr/include/c++/12/string:40,
from /dyninst/src/common/h/entryIDs.h:34,
from /dyninst/src/dataflowAPI/src/RoseInsnFactory.h:34,
from /dyninst/src/dataflowAPI/src/RoseInsnFactory.C:30:
/usr/include/c++/12/bits/stl_construct.h: In instantiation of 'constexpr decltype (::new(void*(0)) _Tp) std::construct_at(_Tp*, _Args&& ...) [with _Tp = Dyninst::InstructionAPI::Operand; _Args = {}; decltype (::new(void*(0)) _Tp) = Dyninst::InstructionAPI::Operand*]':
/usr/include/c++/12/bits/stl_construct.h:115:21: required from 'constexpr void std::_Construct(_Tp*, _Args&& ...) [with _Tp = Dyninst::InstructionAPI::Operand; _Args = {}]'
/usr/include/c++/12/bits/stl_uninitialized.h:638:18: required from 'static constexpr _ForwardIterator std::__uninitialized_default_n_1<_TrivialValueType>::__uninit_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Dyninst::InstructionAPI::Operand*; _Size = long unsigned int; bool _TrivialValueType = false]'
/usr/include/c++/12/bits/stl_uninitialized.h:701:20: required from 'constexpr _ForwardIterator std::__uninitialized_default_n(_ForwardIterator, _Size) [with _ForwardIterator = Dyninst::InstructionAPI::Operand*; _Size = long unsigned int]'
/usr/include/c++/12/bits/stl_uninitialized.h:766:44: required from 'constexpr _ForwardIterator std::__uninitialized_default_n_a(_ForwardIterator, _Size, allocator<_Tp>&) [with _ForwardIterator = Dyninst::InstructionAPI::Operand*; _Size = long unsigned int; _Tp = Dyninst::InstructionAPI::Operand]'
/usr/include/c++/12/bits/vector.tcc:644:35: required from 'constexpr void std::vector<_Tp, _Alloc>::_M_default_append(size_type) [with _Tp = Dyninst::InstructionAPI::Operand; _Alloc = std::allocator<Dyninst::InstructionAPI::Operand>; size_type = long unsigned int]'
/usr/include/c++/12/bits/stl_vector.h:1011:4: required from 'constexpr void std::vector<_Tp, _Alloc>::resize(size_type) [with _Tp = Dyninst::InstructionAPI::Operand; _Alloc = std::allocator<Dyninst::InstructionAPI::Operand>; size_type = long unsigned int]'
/dyninst/src/dataflowAPI/src/RoseInsnFactory.C:152:20: required from here
/usr/include/c++/12/bits/stl_construct.h:95:14: error: noexcept-expression evaluates to 'false' because of a call to 'Dyninst::InstructionAPI::Operand::Operand(Dyninst::InstructionAPI::Expression::Ptr, bool, bool, bool, bool, bool)' [-Werror=noexcept]
95 | noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...)))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /dyninst/src/instructionAPI/h/Instruction.h:43,
from /dyninst/src/dataflowAPI/src/RoseInsnFactory.h:40:
/dyninst/src/instructionAPI/h/Operand.h:69:16: note: but 'Dyninst::InstructionAPI::Operand::Operand(Dyninst::InstructionAPI::Expression::Ptr, bool, bool, bool, bool, bool)' does not throw; perhaps it should be declared 'noexcept'
69 | explicit Operand(Expression::Ptr val = {}, bool read = false, bool written = false, bool implicit = false,
| ^~~~~~~
cc1plus: all warnings being treated as errors
gmake[2]: *** [parseAPI/CMakeFiles/parseAPI.dir/build.make:678: parseAPI/CMakeFiles/parseAPI.dir/__/dataflowAPI/src/RoseInsnFactory.C.o] Error 1
gmake[2]: *** Waiting for unfinished jobs....
gmake[1]: *** [CMakeFiles/Makefile2:471: parseAPI/CMakeFiles/parseAPI.dir/all] Error 2
gmake: *** [Makefile:136: all] Error 2
Error: Process completed with exit code 2.
|