================
@@ -0,0 +1,251 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,c_diagnostics 
-Wmissing-format-attribute %s
+// RUN: %clang_cc1 -fsyntax-only -Wmissing-format-attribute 
-fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics 
-Wmissing-format-attribute %s
+// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics 
-std=c++2b -Wmissing-format-attribute %s
+// RUN: %clang_cc1 -fsyntax-only -x c++ -verify=expected,cpp_diagnostics 
-std=c++23 -Wmissing-format-attribute %s
+// RUN: %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute 
-fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
+
+#ifndef __cplusplus
+typedef __CHAR16_TYPE__ char16_t;
+typedef __CHAR32_TYPE__ char32_t;
+typedef __WCHAR_TYPE__ wchar_t;
+#endif
+
+typedef __SIZE_TYPE__ size_t;
+typedef __builtin_va_list va_list;
+
+__attribute__((__format__(__printf__, 1, 2)))
+int printf(const char *, ...); // #printf
+
+__attribute__((__format__(__scanf__, 1, 2)))
+int scanf(const char *, ...); // #scanf
+
+__attribute__((__format__(__printf__, 1, 0)))
+int vprintf(const char *, va_list); // #vprintf
+
+__attribute__((__format__(__scanf__, 1, 0)))
+int vscanf(const char *, va_list); // #vscanf
+
+__attribute__((__format__(__printf__, 2, 0)))
+int vsprintf(char *, const char *, va_list); // #vsprintf
+
+__attribute__((__format__(__printf__, 3, 0)))
+int vsnprintf(char *ch, size_t, const char *, va_list); // #vsnprintf
+
+#ifndef __cplusplus
+int vwscanf(const wchar_t *, va_list); // #vwscanf
+#endif
+
+__attribute__((__format__(__scanf__, 1, 4)))
+void f1(char *out, const size_t len, const char *format, ... /* args */) // #f1
+{
+    va_list args;
+    vsnprintf(out, len, format, args); // expected-no-warning@#f1
+}
+
+__attribute__((__format__(__printf__, 1, 4)))
+void f2(char *out, const size_t len, const char *format, ... /* args */) // #f2
+{
+    va_list args;
+    vsnprintf(out, len, format, args); // expected-warning@#f2 {{diagnostic 
behavior may be improved by adding the 'printf' format attribute to the 
declaration of 'f2'}}
----------------
aaronpuchert wrote:

I think we should warn on the call where we found out. Yes, the declaration is 
where the fix should be, but this is typically indicated with a note. The 
warning should be where we see the issue. The issue can not be seen in the 
declaration, but in the call forwarding the parameter.

Another reason is that the attribute should be added to the declaration in a 
header file, not to the definition in the source file.

The reason why for example `-Wmissing-noreturn` behaves different is that there 
is no place in the function body where we notice that the function never 
returns. It's a control flow graph walk that finds no paths to a return. On the 
other hand:
```c++
bool b;
[[noreturn]] void f() {
  if (b) return;
}
```
produces
```
<stdin>:3:10: warning: function 'f' declared 'noreturn' should not return 
[-Winvalid-noreturn]
    3 |   if (b) return;
      |          ^
<stdin>:4:1: warning: function declared 'noreturn' should not return 
[-Winvalid-noreturn]
    4 | }
      | ^
```
GCC emits the warning on the forwarded parameter. In the `printf` test case:
```
    vprintf(out, args);
            ^
```

https://github.com/llvm/llvm-project/pull/105479
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to