diff --git a/stl/inc/xmemory b/stl/inc/xmemory index a5efe18040..462a7465fc 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1602,7 +1602,7 @@ void _Return_temporary_buffer(_Ty* const _Pbuf) noexcept { } template -void _Construct_in_place_by_deref(_Ty& _Val, const _InIt& _Iter) +void _Construct_in_place_by_deref(_Ty& _Val, _InIt& _Iter) noexcept(noexcept(::new (static_cast(_STD addressof(_Val))) _Ty(*_Iter))) { ::new (static_cast(_STD addressof(_Val))) _Ty(*_Iter); } @@ -1632,14 +1632,14 @@ struct _NODISCARD _Uninitialized_backout { } template - void _Emplace_back_deref(const _InIt& _Iter) { + void _Emplace_back_deref(_InIt& _Iter) { // construct a new element at *_Last from the result of dereferencing _Iter and increment. _STD _Construct_in_place_by_deref(*_Last, _Iter); ++_Last; } template - void _Emplace_back_deref_move(const _InIt& _Iter) { + void _Emplace_back_deref_move(_InIt& _Iter) { // construct a new element at *_Last from the result of dereferencing _Iter and increment, // with lvalue cast to xvalue if necessary for uninitialized_move(_n). if constexpr (is_lvalue_reference_v) { diff --git a/tests/std/test.lst b/tests/std/test.lst index 7b8847181e..4e38b8fb26 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -782,3 +782,4 @@ tests\VSO_1775715_user_defined_modules tests\VSO_1804139_static_analysis_warning_with_single_element_array tests\VSO_1925201_iter_traits tests\VSO_2252142_wrong_C5046 +tests\VSO_2318081_bogus_const_overloading diff --git a/tests/std/tests/VSO_2318081_bogus_const_overloading/env.lst b/tests/std/tests/VSO_2318081_bogus_const_overloading/env.lst new file mode 100644 index 0000000000..19f025bd0e --- /dev/null +++ b/tests/std/tests/VSO_2318081_bogus_const_overloading/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/VSO_2318081_bogus_const_overloading/test.compile.pass.cpp b/tests/std/tests/VSO_2318081_bogus_const_overloading/test.compile.pass.cpp new file mode 100644 index 0000000000..06f234bd56 --- /dev/null +++ b/tests/std/tests/VSO_2318081_bogus_const_overloading/test.compile.pass.cpp @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +using namespace std; + +// VSO-2318081 "[RWC][prod/fe][Regression] 4 projects failed with error C2440: +// 'initializing': cannot convert from 'const llvm::Value *' to '_Ty'" + +struct Thing {}; + +struct BogusInIt { + using iterator_category = input_iterator_tag; + using value_type = Thing*; + using difference_type = ptrdiff_t; + using pointer = void; + using reference = Thing*; + + BogusInIt& operator++(); + BogusInIt operator++(int); + friend bool operator==(const BogusInIt&, const BogusInIt&); + friend bool operator!=(const BogusInIt&, const BogusInIt&); + + // This single overload would be conforming: + // Thing* operator*() const; + + // N4993 [iterator.cpp17.general]/1 and [tab:inputiterator] forbid overloading operator*() + // with varying return types, but uninitialized_meow() tolerated this before GH-5135. + + // See LLVM-119084, reported on 2024-12-07. After that has been fixed and propagated throughout the ecosystem, + // we should consider making the STL strictly reject such bogus iterators and removing this test coverage. + Thing* operator*(); + const Thing* operator*() const; +}; + +void test() { + BogusInIt src{}; + Thing** dest{nullptr}; + + uninitialized_copy(src, src, dest); + uninitialized_copy_n(src, 0, dest); +#if _HAS_CXX17 + uninitialized_move(src, src, dest); + uninitialized_move_n(src, 0, dest); +#endif // _HAS_CXX17 +}