c42f / tinyformat

Minimal, type safe printf replacement library for C++
532 stars 75 forks source link

printf issue with VS2013 x64 #20

Closed kainjow closed 9 years ago

kainjow commented 9 years ago

MSVC is generating format errors for ints when using tiny format::printf in Visual Studio 2013 Update 3 targeting x64 using this code:

std::string weekday = "Wednesday";
const char* month = "July";
size_t day = 27;
long hour = 14;
int min = 44;
tfm::printf("%s, %s %d, %.2d:%.2d\n", weekday, month, day, hour, min);
warning C4313: 'printf' : '%d' in format string conflicts with argument 3 of type 'const size_t *'

I get this warning for each int. If I build targeting 32-bit it works fine. I'm not sure what's going on. It seems to think the argument type is a pointer. I wonder if this is a bug?

If I use tfm::format to generate a string, it works fine.

kainjow commented 9 years ago

OK I am able to reproduce the issue outside of tinyformat:

namespace test {
    void printf(const char *fmt, const int& value) {
    }
}
int main() {
    test::printf("%d\n", 10);
    return 0;
}

This gives the same error. If I remove the reference from value so it's const int value then MSVC doesn't complain.

I guess just another fine example of MSVC :)

c42f commented 9 years ago

That's a good reduction of the test case, cheers.

It seems fairly clear that this is an MSVC bug where you can't have a function called printf() (even in your own namespace!) without MSVC trying to do some format string checking. Insanity. Perhaps you could report this test case to the Microsoft compiler team?

I suspect there's not much we can do to work around it - we can't change the pass by reference to pass by value without an unacceptable loss of generality. With that in mind I'm going to close this issue, but if you can find a neat workaround I'd be more than happy to accept a patch.

Of course, you can always define your own wrapper as follows:

template<typename... Args>
void myprintf(const char* fmt, const Args&... args)
{
    tfm::format(std::cout, fmt, args...);
}

but that's not very satisfying.

kainjow commented 9 years ago

I think the best workaround is to just disable that warning altogether, which I did via the project's Properties > Configuration Properties > C/C++ > Advanced and added 4313 to Disabled Specific Warnings.

c42f commented 9 years ago

Of course, good point. Would you be able to do this in the tinyformat header with some appropriate pragma warning(push), pragma warning(disable:4313) and pragma warning(pop) around printf()? Perhaps that doesn't work though, since the warning is probably triggered at the usage site.

If not, I'll close this issue again (would try the above myself, but I don't have a copy of VS2013)

kainjow commented 9 years ago

yes, the error is at the usage of the function, not at the implementation.

c42f commented 9 years ago

Ok, it seems like there's not much we can do to mitigate this one.