Skip to content

Commit 1e312b3

Browse files
Don't deduce the return type of emplace{,_back,_front} (#4963)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 7b154c5 commit 1e312b3

File tree

10 files changed

+76
-9
lines changed

10 files changed

+76
-9
lines changed

stl/inc/deque

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ private:
11621162

11631163
public:
11641164
template <class... _Valty>
1165-
decltype(auto) emplace_front(_Valty&&... _Val) {
1165+
_CONTAINER_EMPLACE_RETURN emplace_front(_Valty&&... _Val) {
11661166
_Orphan_all();
11671167
_Emplace_front_internal(_STD forward<_Valty>(_Val)...);
11681168
#if _HAS_CXX17
@@ -1171,7 +1171,7 @@ public:
11711171
}
11721172

11731173
template <class... _Valty>
1174-
decltype(auto) emplace_back(_Valty&&... _Val) {
1174+
_CONTAINER_EMPLACE_RETURN emplace_back(_Valty&&... _Val) {
11751175
_Orphan_all();
11761176
_Emplace_back_internal(_STD forward<_Valty>(_Val)...);
11771177

stl/inc/forward_list

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -700,7 +700,7 @@ public:
700700
}
701701

702702
template <class... _Valty>
703-
decltype(auto) emplace_front(_Valty&&... _Val) { // insert element at beginning
703+
_CONTAINER_EMPLACE_RETURN emplace_front(_Valty&&... _Val) { // insert element at beginning
704704
_Insert_after(_Mypair._Myval2._Before_head(), _STD forward<_Valty>(_Val)...);
705705

706706
#if _HAS_CXX17

stl/inc/list

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ public:
981981
}
982982

983983
template <class... _Valty>
984-
decltype(auto) emplace_front(_Valty&&... _Val) { // insert element at beginning
984+
_CONTAINER_EMPLACE_RETURN emplace_front(_Valty&&... _Val) { // insert element at beginning
985985
reference _Result = _Emplace(_Mypair._Myval2._Myhead->_Next, _STD forward<_Valty>(_Val)...)->_Myval;
986986

987987
#if _HAS_CXX17
@@ -992,7 +992,7 @@ public:
992992
}
993993

994994
template <class... _Valty>
995-
decltype(auto) emplace_back(_Valty&&... _Val) { // insert element at end
995+
_CONTAINER_EMPLACE_RETURN emplace_back(_Valty&&... _Val) { // insert element at end
996996
reference _Result = _Emplace(_Mypair._Myval2._Myhead, _STD forward<_Valty>(_Val)...)->_Myval;
997997

998998
#if _HAS_CXX17

stl/inc/queue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public:
135135
#endif // _HAS_CXX23
136136

137137
template <class... _Valty>
138-
decltype(auto) emplace(_Valty&&... _Val) {
138+
_CONTAINER_EMPLACE_RETURN emplace(_Valty&&... _Val) {
139139
#if _HAS_CXX17
140140
return c.emplace_back(_STD forward<_Valty>(_Val)...);
141141
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv

stl/inc/stack

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ public:
120120
#endif // _HAS_CXX23
121121

122122
template <class... _Valty>
123-
decltype(auto) emplace(_Valty&&... _Val) {
123+
_CONTAINER_EMPLACE_RETURN emplace(_Valty&&... _Val) {
124124
#if _HAS_CXX17
125125
return c.emplace_back(_STD forward<_Valty>(_Val)...);
126126
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv

stl/inc/vector

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -853,7 +853,7 @@ private:
853853

854854
public:
855855
template <class... _Valty>
856-
_CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) {
856+
_CONSTEXPR20 _CONTAINER_EMPLACE_RETURN emplace_back(_Valty&&... _Val) {
857857
// insert by perfectly forwarding into element at end, provide strong guarantee
858858
_Ty& _Result = _Emplace_one_at_back(_STD forward<_Valty>(_Val)...);
859859
#if _HAS_CXX17
@@ -2979,7 +2979,7 @@ public:
29792979
}
29802980

29812981
template <class... _Valty>
2982-
_CONSTEXPR20 decltype(auto) emplace_back(_Valty&&... _Val) {
2982+
_CONSTEXPR20 _CONTAINER_EMPLACE_RETURN emplace_back(_Valty&&... _Val) {
29832983
bool _Tmp(_STD forward<_Valty>(_Val)...);
29842984
push_back(_Tmp);
29852985

stl/inc/xmemory

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2643,6 +2643,12 @@ _NODISCARD _Elem* _UIntegral_to_buff(_Elem* _RNext, _UTy _UVal) { // used by bot
26432643
}
26442644
_STD_END
26452645

2646+
#if _HAS_CXX17
2647+
#define _CONTAINER_EMPLACE_RETURN reference
2648+
#else // ^^^ _HAS_CXX17 ^^^ / vvv !_HAS_CXX17 vvv
2649+
#define _CONTAINER_EMPLACE_RETURN void
2650+
#endif // ^^^ !_HAS_CXX17 ^^^
2651+
26462652
#pragma pop_macro("new")
26472653
_STL_RESTORE_CLANG_WARNINGS
26482654
#pragma warning(pop)

tests/std/test.lst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,3 +771,4 @@ tests\VSO_0971246_legacy_await_headers
771771
tests\VSO_1775715_user_defined_modules
772772
tests\VSO_1804139_static_analysis_warning_with_single_element_array
773773
tests\VSO_1925201_iter_traits
774+
tests\VSO_2252142_wrong_C5046
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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3+
4+
#include <deque>
5+
#include <forward_list>
6+
#include <list>
7+
#include <queue>
8+
#include <stack>
9+
#include <type_traits>
10+
#include <utility>
11+
#include <vector>
12+
13+
// Test for DevCom-10745303 / VSO-2252142 "C5046 is wrongly triggered in unevaluated context"
14+
15+
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
16+
17+
using namespace std;
18+
19+
template <class T>
20+
struct convertible_to_any {
21+
operator T() &&; // not defined, only used in unevaluated context
22+
};
23+
24+
template <class Cont, class = void>
25+
constexpr bool has_emplace = false;
26+
template <class Cont>
27+
constexpr bool has_emplace<Cont,
28+
void_t<decltype(declval<Cont&>().emplace(declval<convertible_to_any<typename Cont::value_type>>()))>> = true;
29+
30+
template <class Cont, class = void>
31+
constexpr bool has_emplace_back = false;
32+
template <class Cont>
33+
constexpr bool has_emplace_back<Cont,
34+
void_t<decltype(declval<Cont&>().emplace_back(declval<convertible_to_any<typename Cont::value_type>>()))>> = true;
35+
36+
template <class Cont, class = void>
37+
constexpr bool has_emplace_front = false;
38+
template <class Cont>
39+
constexpr bool has_emplace_front<Cont,
40+
void_t<decltype(declval<Cont&>().emplace_front(declval<convertible_to_any<typename Cont::value_type>>()))>> = true;
41+
42+
namespace {
43+
struct S2 {};
44+
} // namespace
45+
46+
// Was emitting "warning C5046: Symbol involving type with internal linkage not defined"
47+
// as a consequence of our use of return type deduction for the pertinent container functions.
48+
STATIC_ASSERT(has_emplace_back<vector<S2>>);
49+
STATIC_ASSERT(has_emplace_back<deque<S2>>);
50+
STATIC_ASSERT(has_emplace_front<deque<S2>>);
51+
STATIC_ASSERT(has_emplace_front<forward_list<S2>>);
52+
STATIC_ASSERT(has_emplace_back<list<S2>>);
53+
STATIC_ASSERT(has_emplace_front<list<S2>>);
54+
STATIC_ASSERT(has_emplace<queue<S2>>);
55+
STATIC_ASSERT(has_emplace<stack<S2>>);
56+
STATIC_ASSERT(has_emplace_back<vector<bool>>); // Cannot trigger this bug, but for consistency

0 commit comments

Comments
 (0)