Skip to content

Commit 0372e78

Browse files
<xmemory>: Tolerate bogus const-overloading in iterators passed to uninitialized_meow() (#5170)
1 parent 1a31980 commit 0372e78

File tree

4 files changed

+56
-3
lines changed

4 files changed

+56
-3
lines changed

stl/inc/xmemory

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,7 +1602,7 @@ void _Return_temporary_buffer(_Ty* const _Pbuf) noexcept {
16021602
}
16031603

16041604
template <class _Ty, class _InIt>
1605-
void _Construct_in_place_by_deref(_Ty& _Val, const _InIt& _Iter)
1605+
void _Construct_in_place_by_deref(_Ty& _Val, _InIt& _Iter)
16061606
noexcept(noexcept(::new (static_cast<void*>(_STD addressof(_Val))) _Ty(*_Iter))) {
16071607
::new (static_cast<void*>(_STD addressof(_Val))) _Ty(*_Iter);
16081608
}
@@ -1632,14 +1632,14 @@ struct _NODISCARD _Uninitialized_backout {
16321632
}
16331633

16341634
template <class _InIt>
1635-
void _Emplace_back_deref(const _InIt& _Iter) {
1635+
void _Emplace_back_deref(_InIt& _Iter) {
16361636
// construct a new element at *_Last from the result of dereferencing _Iter and increment.
16371637
_STD _Construct_in_place_by_deref(*_Last, _Iter);
16381638
++_Last;
16391639
}
16401640

16411641
template <class _InIt>
1642-
void _Emplace_back_deref_move(const _InIt& _Iter) {
1642+
void _Emplace_back_deref_move(_InIt& _Iter) {
16431643
// construct a new element at *_Last from the result of dereferencing _Iter and increment,
16441644
// with lvalue cast to xvalue if necessary for uninitialized_move(_n).
16451645
if constexpr (is_lvalue_reference_v<decltype(*_Iter)>) {

tests/std/test.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,3 +782,4 @@ tests\VSO_1775715_user_defined_modules
782782
tests\VSO_1804139_static_analysis_warning_with_single_element_array
783783
tests\VSO_1925201_iter_traits
784784
tests\VSO_2252142_wrong_C5046
785+
tests\VSO_2318081_bogus_const_overloading
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Copyright (c) Microsoft Corporation.
2+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
RUNALL_INCLUDE ..\usual_matrix.lst
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <cstddef>
5+
#include <iterator>
6+
#include <memory>
7+
using namespace std;
8+
9+
// VSO-2318081 "[RWC][prod/fe][Regression] 4 projects failed with error C2440:
10+
// 'initializing': cannot convert from 'const llvm::Value *' to '_Ty'"
11+
12+
struct Thing {};
13+
14+
struct BogusInIt {
15+
using iterator_category = input_iterator_tag;
16+
using value_type = Thing*;
17+
using difference_type = ptrdiff_t;
18+
using pointer = void;
19+
using reference = Thing*;
20+
21+
BogusInIt& operator++();
22+
BogusInIt operator++(int);
23+
friend bool operator==(const BogusInIt&, const BogusInIt&);
24+
friend bool operator!=(const BogusInIt&, const BogusInIt&);
25+
26+
// This single overload would be conforming:
27+
// Thing* operator*() const;
28+
29+
// N4993 [iterator.cpp17.general]/1 and [tab:inputiterator] forbid overloading operator*()
30+
// with varying return types, but uninitialized_meow() tolerated this before GH-5135.
31+
32+
// See LLVM-119084, reported on 2024-12-07. After that has been fixed and propagated throughout the ecosystem,
33+
// we should consider making the STL strictly reject such bogus iterators and removing this test coverage.
34+
Thing* operator*();
35+
const Thing* operator*() const;
36+
};
37+
38+
void test() {
39+
BogusInIt src{};
40+
Thing** dest{nullptr};
41+
42+
uninitialized_copy(src, src, dest);
43+
uninitialized_copy_n(src, 0, dest);
44+
#if _HAS_CXX17
45+
uninitialized_move(src, src, dest);
46+
uninitialized_move_n(src, 0, dest);
47+
#endif // _HAS_CXX17
48+
}

0 commit comments

Comments
 (0)