[clang] [clang] Catch missing format attributes (PR #70024)

Aaron Puchert via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 10 14:06:44 PST 2023


================
@@ -0,0 +1,132 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wmissing-format-attribute %s
+
+#include <iostream>
+#include <cstdarg>
+
+void f1(const std::string &str, ... /* args */)
+{
+    va_list args;
+    vscanf(str.c_str(), args); // no warning
+    vprintf(str.c_str(), args); // no warning
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error: {{format argument not a string type}}
+void f2(const std::string &str, ... /* args */);
+
+void f3(std::string_view str, ... /* args */)
+{
+    va_list args;
+    vscanf(std::string(str).c_str(), args); // no warning
+    vprintf(std::string(str).c_str(), args); // no warning
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
+void f4(std::string_view str, ... /* args */);
+
+void f5(const std::wstring &str, ... /* args */)
+{
+    va_list args;
+    vscanf((const char *)str.c_str(), args); // no warning
+    vprintf((const char *)str.c_str(), args); // no warning
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
+void f6(const std::wstring &str, ... /* args */);
+
+void f7(std::wstring_view str, ... /* args */)
+{
+    va_list args;
+    vscanf((const char *) std::wstring(str).c_str(), args); // no warning
+    vprintf((const char *) std::wstring(str).c_str(), args); // no warning
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
+void f8(std::wstring_view str, ... /* args */);
+
+void f9(const wchar_t *out, ... /* args */)
+{
+    va_list args;
+    vprintf(out, args); // expected-error {{no matching function for call to 'vprintf'}}
+    vscanf((const char *) out, args); // no warning
+    vscanf((char *) out, args); // no warning
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
+void f10(const wchar_t *out, ... /* args */);
+
+void f11(const char16_t *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+__attribute__((format(printf, 1, 2))) // expected-error {{format argument not a string type}}
+void f12(const char16_t *out, ... /* args */);
+
+void f13(const char32_t *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+__attribute__((format(scanf, 1, 2))) // expected-error {{format argument not a string type}}
+void f14(const char32_t *out, ... /* args */);
+
+void f15(const char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f15'}}
+}
+
+__attribute__((format(scanf, 1, 2)))
+void f16(const char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // no warning
+}
+
+void f17(const unsigned char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+__attribute__((format(scanf, 1, 2)))
+void f18(const unsigned char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+void f19(const signed char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+__attribute__((format(scanf, 1, 2)))
+void f20(const signed char *out, ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-error {{no matching function for call to 'vscanf'}}
+}
+
+void f21(const char out[], ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f21'}}
+}
+
+__attribute__((format(scanf, 1, 2)))
+void f22(const char out[], ... /* args */)
+{
+    va_list args;
+    vscanf(out, args); // no warning
+}
+
+template <int N>
+void func(char (&str)[N], ...)
+{
+    va_list args;
+    vprintf(str, args); // no warning
+}
----------------
aaronpuchert wrote:

What makes C++ interesting is the implicit `this` parameter in non-static member functions, maybe you can add tests for that? The existing tests here seem to be mostly about cases where the attribute does not apply due to some technicality.

https://github.com/llvm/llvm-project/pull/70024


More information about the cfe-commits mailing list