llvm-project/clang/test/Sema/format-attr-missing.cpp
Vladimir Vuksanovic 1df7b512bd
[Sema] Suggest missing format attributes (#166738)
Implements the `-Wmissing-format-attribute` diagnostic as a subgroup of
`-Wformat-nonliteral`. It suggests adding format attributes to function
declarations that call other format functions and pass the format string
to them.

This is an updated implementation of #105479.

---------

Co-authored-by: Budimir Arandjelovic <budimir.arandjelovic@htecgroup.com>
2025-12-05 09:04:12 -05:00

69 lines
2.8 KiB
C++

// RUN: %clang_cc1 -fsyntax-only -verify -std=c++23 -Wmissing-format-attribute %s
// RUN: %clang_cc1 -fsyntax-only -Wmissing-format-attribute -fdiagnostics-parseable-fixits -std=c++23 %s 2>&1 | FileCheck %s
typedef __SIZE_TYPE__ size_t;
typedef __builtin_va_list va_list;
[[gnu::format(printf, 1, 2)]]
int printf(const char *, ...);
[[gnu::format(scanf, 1, 2)]]
int scanf(const char *, ...);
[[gnu::format(printf, 1, 0)]]
int vprintf(const char *, va_list);
[[gnu::format(scanf, 1, 0)]]
int vscanf(const char *, va_list);
[[gnu::format(printf, 2, 0)]]
int vsprintf(char *, const char *, va_list);
[[gnu::format(printf, 3, 0)]]
int vsnprintf(char *, size_t, const char *, va_list);
struct S1
{
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:3-[[@LINE+1]]:3}:"{{\[\[}}gnu::format(scanf, 2, 3)]] "
void fn1(const char *out, ... /* args */) // #S1_fn1
{
va_list args;
vscanf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(scanf, 2, 3)' attribute to the declaration of 'fn1'}}
// expected-note@#S1_fn1 {{'fn1' declared here}}
}
[[gnu::format(printf, 2, 0)]]
void print(const char *out, va_list args);
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:3-[[@LINE+1]]:3}:"{{\[\[}}gnu::format(printf, 2, 3)]] "
void fn2(const char *out, ... /* args */) // #S1_fn2
{
va_list args;
print(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 3)' attribute to the declaration of 'fn2'}}
// expected-note@#S1_fn2 {{'fn2' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:3-[[@LINE+1]]:3}:"{{\[\[}}gnu::format(printf, 2, 0)]] "
void fn3(const char *out, va_list args) // #S1_fn3
{
print(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 0)' attribute to the declaration of 'fn3'}}
// expected-note@#S1_fn3 {{'fn3' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:3-[[@LINE+1]]:3}:"{{\[\[}}gnu::format(printf, 2, 3)]] "
void fn4(this S1& self, const char *out, ... /* args */) // #S1_fn4
{
va_list args;
self.print(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 3)' attribute to the declaration of 'fn4'}}
// expected-note@#S1_fn4 {{'fn4' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:3-[[@LINE+1]]:3}:"{{\[\[}}gnu::format(printf, 2, 0)]] "
void fn5(this S1& self, const char *out, va_list args) // #S1_fn5
{
self.print(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 0)' attribute to the declaration of 'fn5'}}
// expected-note@#S1_fn5 {{'fn5' declared here}}
}
};