Last active
December 16, 2020 21:50
-
-
Save jstine35/646097d6534a5292475e423f84c73710 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
// ENABLE_PRINTF_VERIFY_CHECK_ON_MSVC | |
// | |
// Microsoft doesn't provide a way to annoate custom-rolled user printf() functions for static analysis. | |
// Well, ok -- it does provide _Printf_format_string_ but that's only effective when using the Code Analysis | |
// tool which is both incrediously slow and generates a hundred false positives for every valid issue. In | |
// other words, useless. | |
// | |
// The upside is MSVC does perform automatic lightweight static analysis on printf() builtin functions as part | |
// of the regular build process. So I did a horrible thing and I built a macro that fake-calls MSVC's snprintf() | |
// on the input string, implemented as the second half of a nullified conditional such that it never _actually_ | |
// gets run. All tokens from the format macro do get pasted twice as part of this process, though only one of | |
// the pastes is reachable. Behavior of the __COUNTER__ macro in this case would change. No other program | |
// behavior should be affected. --jstine | |
// | |
// Usage example: | |
// #define myFooPrintf(fmt, ...) (VERIFY_PRINTF_ON_MSVC(fmt, __VA_ARGS__), _myFooPrintf(fmt, ## __VA_ARGS__)) | |
// | |
#if !defined(ENABLE_PRINTF_VERIFY_CHECK_ON_MSVC) | |
# if defined(_MSC_VER) | |
# define ENABLE_PRINTF_VERIFY_CHECK_ON_MSVC 1 | |
# else | |
# define ENABLE_PRINTF_VERIFY_CHECK_ON_MSVC 0 | |
# endif | |
#endif | |
#if !defined(VERIFY_PRINTF_ON_MSVC) | |
# if ENABLE_PRINTF_VERIFY_CHECK_ON_MSVC | |
# define VERIFY_PRINTF_ON_MSVC(...) (0 && snprintf(nullptr, 0, ## __VA_ARGS__)) | |
# if defined(__cplusplus) | |
// in C++ we can allow macros where-in the format parameter is optional, typical of macros that | |
// translate an empty format into a newline or such. | |
// (ex, myPrintLine() being equivalent to myPrintLine("")) | |
static inline int snprintf(const char* fmt, int len) { | |
return 0; | |
} | |
# endif | |
# else | |
# define VERIFY_PRINTF_ON_MSVC(...) (0) | |
# endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment