// compiler specific attribute translation
// msvc should come first, so if clang is in msvc mode it gets the right defines
+// NOTE: this will only do checking in msvc with versions that support /analyze
+#if _MSC_VER
+# ifdef _USE_ATTRIBUTES_FOR_SAL
+# undef _USE_ATTRIBUTES_FOR_SAL
+# endif
+# define _USE_ATTRIBUTES_FOR_SAL 1
+# include <sal.h>
+# define FOLLY_PRINTF_FORMAT _Printf_format_string_
+# define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) /**/
+#else
+# define FOLLY_PRINTF_FORMAT /**/
+# define FOLLY_PRINTF_FORMAT_ATTR(format_param, dots_param) \
+ __attribute__((format(printf, format_param, dots_param)))
+#endif
+
// noreturn
#if defined(_MSC_VER)
# define FOLLY_NORETURN __declspec(noreturn)
* resulting string, and the second appends the produced characters to
* the specified string and returns a reference to it.
*/
-std::string stringPrintf(const char* format, ...)
- __attribute__ ((format (printf, 1, 2)));
+std::string stringPrintf(FOLLY_PRINTF_FORMAT const char* format, ...)
+ FOLLY_PRINTF_FORMAT_ATTR(1, 2);
-/** Similar to stringPrintf, with different signiture.
- */
-void stringPrintf(std::string* out, const char* fmt, ...)
- __attribute__ ((format (printf, 2, 3)));
+/* Similar to stringPrintf, with different signature. */
+void stringPrintf(std::string* out, FOLLY_PRINTF_FORMAT const char* fmt, ...)
+ FOLLY_PRINTF_FORMAT_ATTR(2, 3);
-std::string& stringAppendf(std::string* output, const char* format, ...)
- __attribute__ ((format (printf, 2, 3)));
+std::string& stringAppendf(std::string* output,
+ FOLLY_PRINTF_FORMAT const char* format, ...)
+ FOLLY_PRINTF_FORMAT_ATTR(2, 3);
/**
* Backslashify a string, that is, replace non-printable characters