A recent Visual Studio Studio upgrade to version 15.6.2 included a Visual C++ compiler update which causes warnings for the following code at the push_back
line due to [[nodiscard]]
:
#include <vector>
struct [[nodiscard]] S
{
int i;
};
int main()
{
std::vector<S> v;
v.push_back({ 1 }); // causes warning C4834
}
The compiler is invoked like this (note that no high warning level needs to be specified to reproduce, but /std:c++latest
is required, and /permissive-
is optional):
cl /nologo /EHsc /permissive- /std:c++latest test.cpp
The warning comes from within Visual C++'s own std::vector
-implementation code and says:
warning C4834: discarding return value of function with 'nodiscard' attribute
(see below for complete warning output)
Compiler version:
Microsoft (R) C/C++ Optimizing Compiler Version 19.13.26128 for x64
My theory is that this warning is caused by:
push_back
in terms of emplace_back
,emplace_back
returning a reference in C++17, and_HAS_CXX17
macro is set.However, regardless of any internal library code, doesn't Visual C++ violate the standard in producing those diagnostic messages? The latest Clang and GCC versions over at wandbox.org do not produce any warnings for the same code.
I maintain that library-internal usages of nodiscard
user types like S
should never cause warnings, because this would render the feature unusable in practice, but the short description of nodiscard
in §10.6.7/2 [dcl.attr.nodiscard] is a bit vague on that topic.
Or does the standard simply "discourage" such warnings, and it is all really a QoI issue, albeit a rather serious one in this case, so serious that it should probably be filed as a bug report at Microsoft?
Here's the complete warning:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\vector(996): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\vector(995): note: while compiling class template member function 'void std::vector<S,std::allocator<_Ty>>::push_back(_Ty &&)'
with
[
_Ty=S
]
test.cpp(11): note: see reference to function template instantiation 'void std::vector<S,std::allocator<_Ty>>::push_back(_Ty &&)' being compiled
with
[
_Ty=S
]
test.cpp(10): note: see reference to class template instantiation 'std::vector<S,std::allocator<_Ty>>' being compiled
with
[
_Ty=S
]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\vector(1934): warning C4834: discarding return value of function with 'nodiscard' attribute
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\vector(1933): note: while compiling class template member function 'void std::vector<S,std::allocator<_Ty>>::_Umove_if_noexcept1(S *,S *,S *,std::true_type)'
with
[
_Ty=S
]
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.13.26128\include\vector(1944): note: see reference to function template instantiation 'void std::vector<S,std::allocator<_Ty>>::_Umove_if_noexcept1(S *,S *,S *,std::true_type)' being compiled
with
[
_Ty=S
]
However, regardless of any internal library code, doesn't Visual C++ violate the standard in producing those diagnostic messages?
This question doesn't really make sense. The standard mandates that if a program violates a diagnosable rule, an implementation must issue a diagnostic. The standard doesn't say anything about disallowing diagnostics for otherwise well-formed programs.
There are many, many common compiler warnings that are diagnostics on well-formed code. Which is great! It's really a quality of implementation issue to ensure that the warnings you get are valuable. In this case, this obviously is not a valuable warning, so you should submit a bug report to Microsoft. But not because this warning violates the standard - simply because it's not a useful warning.