Patryk Kowalski
Patryk Kowalski

Reputation: 337

GCC/Clang vs. MSVC: Missing Wconversion warning in template function with std::invoke

I'm encountering an issue where a template function uses std::invoke to call another function, passing a size_t argument to a parameter expecting an int32_t. This should, theoretically, trigger a warning about type conversion. However, when compiling with GCC or Clang using the -Wconversion flag, no warning is issued, whereas MSVC correctly reports a warning.

Here's a simplified version of the code:

void expectsInt32(int32_t) {
    /* … */
}

template<typename Func, typename Arg>
void call(Func func, Arg arg) {
    std::invoke(func, arg); // arg is size_t, potentially causing narrowing conversion
}

int main() {
    size_t largeNumber = 4294967295; // Maximum value for uint32_t
    call(expectsInt32, largeNumber); // Compiles without warning in GCC/Clang with -Wconversion
    return 0;
}

On MSVC, this code triggers a warning about the potential data loss during the conversion from size_t to int32_t:

C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): error C2220: the following warning is treated as an error
C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): warning C4267: 'argument': conversion from 'size_t' to 'int32_t', possible loss of data
C:/data/msvc/14.39.33321-Pre/include\type_traits(1739): note: the template instantiation context (the oldest one first) is
<source>(18): note: see reference to function template instantiation 'void call<void(__cdecl *)(int32_t),size_t>(Func,Arg)' being compiled
        with
        [
            Func=void (__cdecl *)(int32_t),
            Arg=size_t
        ]
<source>(12): note: see reference to function template instantiation 'void std::invoke<void(__cdecl *&)(int32_t),Arg&,>(_Callable,_Ty1) noexcept(false)' being compiled
        with
        [
            Arg=size_t,
            _Callable=void (__cdecl *&)(int32_t),
            _Ty1=size_t &
        ]
Compiler returned: 2

However, the same warning is not emitted by GCC or Clang, even with the -Wconversion flag enabled.

Why might GCC/Clang not warn about this implicit conversion in the context of std::invoke with template arguments? Is there a way to enforce such warnings or add static assertions to catch these cases at compile time?

Here's the code reproduced on Compiler Explorer: https://godbolt.org/z/KPPYM8cna

Upvotes: 3

Views: 160

Answers (1)

Alan
Alan

Reputation: 1

Is there a way to enforce such warnings

Yes, with gcc you can use flag -Wsystem-headers along with -Wconversion to enable such warnings. Demo

The warnings are suppressed here because they happen in a system header.

There is a confirmed gcc bug for the same:

Warnings should not be disabled when instantiating templates defined in system headers

Upvotes: 0

Related Questions