Skip to content

Commit

Permalink
<xmemory>: Tolerate bogus const-overloading in iterators passed to …
Browse files Browse the repository at this point in the history
…`uninitialized_meow()` (#5170)
  • Loading branch information
StephanTLavavej authored Dec 13, 2024
1 parent 1a31980 commit 0372e78
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 3 deletions.
6 changes: 3 additions & 3 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1602,7 +1602,7 @@ void _Return_temporary_buffer(_Ty* const _Pbuf) noexcept {
}

template <class _Ty, class _InIt>
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<void*>(_STD addressof(_Val))) _Ty(*_Iter))) {
::new (static_cast<void*>(_STD addressof(_Val))) _Ty(*_Iter);
}
Expand Down Expand Up @@ -1632,14 +1632,14 @@ struct _NODISCARD _Uninitialized_backout {
}

template <class _InIt>
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 <class _InIt>
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<decltype(*_Iter)>) {
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 4 additions & 0 deletions tests/std/tests/VSO_2318081_bogus_const_overloading/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <cstddef>
#include <iterator>
#include <memory>
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
}

0 comments on commit 0372e78

Please sign in to comment.