Why does MSVC not complain about the expression i.str() where i is an int?

Viewed 161

I got some ill-formed code like the following, but it builds with MSVC 19.32.31329 and /std:c++latest.

#include <Windows.h>

template<typename T>
void foo() {
    int i;
    // Can be anything that looks like a function call
    baz(i.str());
}

int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
    int i;
    // The following line is wrong because i has an integral type
    // and doesn't have .str().
    i.str();
}

The code is clearly wrong and shouldn't compile, but it does. Is this a compiler bug?

2 Answers

Yes, this is a compiler bug that was apparently introduced in version 19.32. It can be observed when compiling either with /std:c++latest or /std:c++20.

It appears that anything that's inside a function template can trick MSVC into learning new rules about integral types. As illustrated in the question once the compiler is through parsing foo it will subsequently allow any expression exp of integral type to have any (fantasy) member (such as str()) invoked (verified with integers, floating point values, booleans, pointers and arrays).


A related issue was brought up in a comment on the question.

While the function template foo is instantiated here, MSVC will compile the following code:

extern void bar(int);

template<typename T>
void foo()
{
    int i;
    // This should not compile
    bar(i.str());
}

int WinMain(void*, void*, char*, int)
{
    foo<int>();
}

Although this could be following rule [temp.res.general/6.4] to the letter of the law:

The program is ill-formed, no diagnostic required, if:

  • ...
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or

Indeed, changing int i to auto i = sizeof(T) fails to compile. This might be unrelated.


A bug report has been issued (see this answer).

This is a msvc bug. The program is ill-formed no diagnostic required. This can be seen from temp#res.general6.1 which states:

  1. The validity of a template may be checked prior to any instantiation.

The program is ill-formed, no diagnostic required, if:

  • 6.1) no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or

Additionally, temp#res.general6.4 also applies here:

a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or

(emphasis mine)


A bug report for the same has been submitted as:

The call someint.str() compiles when invalid function template is present

Related