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.as...@gmail.com> 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. _______________________________________________ Dyninst-api mailing list Dyninst-api@cs.wisc.edu https://lists.cs.wisc.edu/mailman/listinfo/dyninst-api