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>
69 lines
2.8 KiB
C++
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}}
|
|
}
|
|
};
|
|
|