c++visual-c++c++17language-lawyernodiscard

Are new C++17 [[nodiscard]] warnings since Visual Studio 15.6.2 compiler update standards-compliant?


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:

  1. Visual C++ implementing push_back in terms of emplace_back,
  2. emplace_back returning a reference in C++17, and
  3. the somewhat curious (to me) implementation of the latter function in Visual C++ if the _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
        ]

Solution

  • 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.