blob: 5133e595315d7881ee6aa7d9b139cf2c47d9b8fd [file] [log] [blame] [edit]
// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 -Wmissing-format-attribute %s
// RUN: %clang_cc1 -fsyntax-only -std=c23 -Wmissing-format-attribute -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
typedef unsigned long size_t;
typedef long ssize_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);
struct tm { unsigned i; };
[[gnu::format(strftime, 3, 0)]]
size_t strftime(char *, size_t, const char *, const struct tm *);
[[gnu::format(strfmon, 3, 4)]]
ssize_t strfmon(char *, size_t, const char *, ...);
[[gnu::format_matches(printf, 1, "%d %f \"'")]]
int custom_print(const char *, va_list);
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 0)]] "
void f1(const char *fmt, va_list args) // #f1
{
vprintf(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 0)' attribute to the declaration of 'f1'}}
// expected-note@#f1 {{'f1' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(scanf, 1, 0)]] "
void f2(const char *fmt, va_list args) // #f2
{
vscanf(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(scanf, 1, 0)' attribute to the declaration of 'f2'}}
// expected-note@#f2 {{'f2' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 2)]] "
void f3(const char *fmt, ... /* args */) // #f3
{
va_list args;
vprintf(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 2)' attribute to the declaration of 'f3'}}
// expected-note@#f3 {{'f3' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(scanf, 1, 2)]] "
void f4(const char *fmt, ... /* args */) // #f4
{
va_list args;
vscanf(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(scanf, 1, 2)' attribute to the declaration of 'f4'}}
// expected-note@#f4 {{'f4' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+2]]:1-[[@LINE+2]]:1}:"{{\[\[}}gnu::format(printf, 2, 3)]] "
[[gnu::format(printf, 1, 3)]]
void f5(char *out, const char *format, ... /* args */) // #f5
{
va_list args;
vsprintf(out, format, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 3)' attribute to the declaration of 'f5'}}
// expected-note@#f5 {{'f5' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+2]]:1-[[@LINE+2]]:1}:"{{\[\[}}gnu::format(printf, 2, 3)]] "
[[gnu::format(scanf, 1, 3)]]
void f6(char *out, const char *format, ... /* args */) // #f6
{
va_list args;
vsprintf(out, format, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 3)' attribute to the declaration of 'f6'}}
// expected-note@#f6 {{'f6' declared here}}
}
// Ok, out is not passed to print functions.
void f7(char* out, ... /* args */)
{
va_list args;
const char *ch = "format";
vprintf(ch, args);
vprintf("test", args);
}
// Ok, format string is not passed to format functions.
void f8(va_list args)
{
const char * const ch = "format";
vprintf(ch, args);
vprintf("test", args);
vscanf(ch, args);
vscanf("test", args);
char out[10];
struct tm tm_arg;
tm_arg.i = 0;
strftime(out, sizeof(out), ch, &tm_arg);
strftime(out, sizeof(out), "test", &tm_arg);
strfmon(out, sizeof(out), ch);
strfmon(out, sizeof(out), "test");
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format_matches(printf, 1, \"%d %f \\\"'\")]] "
void f9(const char *fmt, ...) // #f9
{
va_list args;
custom_print(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format_matches(printf, 1, "%d %f \"'")' attribute to the declaration of 'f9'}}
// expected-note@#f9 {{'f9' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(scanf, 1, 2)]] "
void f10(const char *out, ... /* args */) // #f10
{
va_list args;
vscanf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(scanf, 1, 2)' attribute to the declaration of 'f10'}}
// expected-note@#f10 {{'f10' declared here}}
vprintf(out, args); // expected-warning {{passing 'scanf' format string where 'printf' format string is expected}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 2)]] "
void f11(const char out[], ... /* args */) // #f11
{
va_list args;
char ch[10] = "format";
vprintf(ch, args);
vsprintf(ch, out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 2)' attribute to the declaration of 'f11'}}
// expected-note@#f11 {{'f11' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 0)]] "
void f12(char* out) // #f12
{
va_list args;
const char *ch = "format";
vsprintf(out, ch, args);
vprintf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 0)' attribute to the declaration of 'f12'}}
// expected-note@#f12 {{'f12' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 0)]] "
void f13(char *out, va_list args) // #f13
{
vprintf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 0)' attribute to the declaration of 'f13'}}
// expected-note@#f13 {{'f13' declared here}}
vscanf(out, args); // expected-warning {{passing 'printf' format string where 'scanf' format string is expected}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(scanf, 1, 2)]] "
void f14(char *out, ... /* args */) // #f14
{
va_list args;
vscanf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(scanf, 1, 2)' attribute to the declaration of 'f14'}}
// expected-note@#f14 {{'f14' declared here}}
vscanf(out, args);
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+2]]:1-[[@LINE+2]]:1}:"{{\[\[}}gnu::format(printf, 1, 3)]] "
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 2, 3)]] "
void f15(char *ch, const char *out, ... /* args */) // #f15
{
va_list args;
vprintf(ch, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 3)' attribute to the declaration of 'f15'}}
// expected-note@#f15 {{'f15' declared here}}
vprintf(out, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 2, 3)' attribute to the declaration of 'f15'}}
// expected-note@#f15 {{'f15' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 2)]] "
void f16(const char *a, ...) // #f16
{
va_list args;
const char *const b = a;
vprintf(b, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 2)' attribute to the declaration of 'f16'}}
// expected-note@#f16 {{'f16' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 2)]] "
void f17(char *fmt, unsigned x, unsigned y, unsigned z) // #f17
{
printf(fmt, x, y, z); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 2)' attribute to the declaration of 'f17'}}
// expected-note@#f17 {{'f17' declared here}}
}
void f18(char *fmt, unsigned x, unsigned y, unsigned z) // #f18
{
// Arguments are not passed in the same order.
printf(fmt, x, z, y);
}
void f19(char *out, ... /* args */)
{
printf(out, 1); // No warning, arguments are not passed to printf.
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(strftime, 3, 0)]] "
void f20(char *out, const size_t len, const char *format) // #f20
{
struct tm tm_arg;
tm_arg.i = 0;
strftime(out, len, format, &tm_arg); // expected-warning {{diagnostic behavior may be improved by adding the 'format(strftime, 3, 0)' attribute to the declaration of 'f20'}}
// expected-note@#f20 {{'f20' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(strfmon, 3, 4)]] "
void f21(char *out, const size_t len, const char *format, int x, int y) // #f21
{
strfmon(out, len, format, x, y); // expected-warning {{diagnostic behavior may be improved by adding the 'format(strfmon, 3, 4)' attribute to the declaration of 'f21'}}
// expected-note@#f21 {{'f21' declared here}}
}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:1-[[@LINE+1]]:1}:"{{\[\[}}gnu::format(printf, 1, 2)]] "
void f22(const char *fmt, ... /* args */); // #f22
void f22(const char *fmt, ... /* args */)
{
va_list args;
vprintf(fmt, args); // expected-warning {{diagnostic behavior may be improved by adding the 'format(printf, 1, 2)' attribute to the declaration of 'f22'}}
// expected-note@#f22 {{'f22' declared here}}
}