diff --git a/mongoose.c b/mongoose.c
index 1eb690e719d61967fc7e924b0eb8ca572c314763..cd24eff5b9590b5c97becb9be3809cb7133bf433 100644
--- a/mongoose.c
+++ b/mongoose.c
@@ -547,11 +547,7 @@ void cs_log_set_file(FILE *file);
  * Prints log to the current log file, appends "\n" in the end and flushes the
  * stream.
  */
-void cs_log_printf(const char *fmt, ...)
-#ifdef __GNUC__
-    __attribute__((format(printf, 1, 2)))
-#endif
-    ;
+void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
 
 /*
  * Format and print message `x` with the given level `l`. Example:
diff --git a/mongoose.h b/mongoose.h
index a02d96466857dac372ce5d5f92502e35046441b0..d907c97ee5ea308d88d5c860c26130f80bf1f89f 100644
--- a/mongoose.h
+++ b/mongoose.h
@@ -128,8 +128,18 @@
 
 /* Common stuff */
 
+#if !defined(PRINTF_LIKE)
+#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
+#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
+#else
+#define PRINTF_LIKE(f, a)
+#endif
+#endif
+
 #if !defined(WEAK)
-#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
+#if (defined(__GNUC__) || defined(__clang__) || \
+     defined(__TI_COMPILER_VERSION__)) &&       \
+    !defined(_WIN32)
 #define WEAK __attribute__((weak))
 #else
 #define WEAK
@@ -2397,7 +2407,8 @@ size_t c_strnlen(const char *s, size_t maxlen);
 /*
  * Equivalent of standard `snprintf()`.
  */
-int c_snprintf(char *buf, size_t buf_size, const char *format, ...);
+int c_snprintf(char *buf, size_t buf_size, const char *format, ...)
+    PRINTF_LIKE(3, 4);
 
 /*
  * Equivalent of standard `vsnprintf()`.
@@ -2465,7 +2476,8 @@ int mg_casecmp(const char *s1, const char *s2);
  *
  * The purpose of this is to avoid malloc-ing if generated strings are small.
  */
-int mg_asprintf(char **buf, size_t size, const char *fmt, ...);
+int mg_asprintf(char **buf, size_t size, const char *fmt, ...)
+    PRINTF_LIKE(3, 4);
 
 /* Same as mg_asprintf, but takes varargs list. */
 int mg_avprintf(char **buf, size_t size, const char *fmt, va_list ap);
diff --git a/src/common/cs_dbg.h b/src/common/cs_dbg.h
index 5e96433477471f72d94c154507da1b502f694f16..9e0608ef3e32b30d43ed98e5df69e488cfaa9759 100644
--- a/src/common/cs_dbg.h
+++ b/src/common/cs_dbg.h
@@ -115,11 +115,7 @@ void cs_log_set_file(FILE *file);
  * Prints log to the current log file, appends "\n" in the end and flushes the
  * stream.
  */
-void cs_log_printf(const char *fmt, ...)
-#ifdef __GNUC__
-    __attribute__((format(printf, 1, 2)))
-#endif
-    ;
+void cs_log_printf(const char *fmt, ...) PRINTF_LIKE(1, 2);
 
 /*
  * Format and print message `x` with the given level `l`. Example:
diff --git a/src/common/platform.h b/src/common/platform.h
index b517cab4e45d6535d1afabcc96077a6ae4fcb59d..1b803c9e6a870571cd51653d08fa759dd727a586 100644
--- a/src/common/platform.h
+++ b/src/common/platform.h
@@ -92,8 +92,18 @@
 
 /* Common stuff */
 
+#if !defined(PRINTF_LIKE)
+#if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
+#define PRINTF_LIKE(f, a) __attribute__((format(printf, f, a)))
+#else
+#define PRINTF_LIKE(f, a)
+#endif
+#endif
+
 #if !defined(WEAK)
-#if (defined(__GNUC__) || defined(__TI_COMPILER_VERSION__)) && !defined(_WIN32)
+#if (defined(__GNUC__) || defined(__clang__) || \
+     defined(__TI_COMPILER_VERSION__)) &&       \
+    !defined(_WIN32)
 #define WEAK __attribute__((weak))
 #else
 #define WEAK