blob: 4f9e91eb1becbce9ff47b7b3ceee674e55567a12 [file] [log] [blame]
// 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 --check-prefixes=CHECK,C-CHECK
// 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: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple x86_64-linux %s 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-LIN64
// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple x86_64-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple i386-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
// RUN: not %clang_cc1 -fsyntax-only -x c++ -Wmissing-format-attribute -fdiagnostics-parseable-fixits -triple i386-windows %s 2>&1 | FileCheck %s --check-prefixes=CHECK
#ifndef __cplusplus
typedef unsigned short char16_t;
typedef unsigned int 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
__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'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 3, 4)))"
}
void f3(char *out, va_list args) // #f3
{
vprintf(out, args); // expected-warning@#f3 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f3'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(printf, 1, 0)))"
}
void f4(char* out, ... /* args */) // #f4
{
va_list args;
vprintf("test", args); // expected-no-warning@#f4
const char *ch;
vprintf(ch, args); // expected-no-warning@#f4
}
void f5(va_list args) // #f5
{
char *ch;
vscanf(ch, args); // expected-no-warning@#f5
}
void f6(char *out, va_list args) // #f6
{
char *ch;
vprintf(ch, args); // expected-no-warning@#f6
vprintf("test", args); // expected-no-warning@#f6
vprintf(out, args); // expected-warning@#f6 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f6'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 0)))"
}
void f7(const char *out, ... /* args */) // #f7
{
va_list args;
vscanf(out, &args[0]); // expected-warning@#f7 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f7'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-5]]:6-[[@LINE-5]]:6}:"__attribute__((format(scanf, 1, 0)))"
}
void f8(const char *out, ... /* args */) // #f8
{
va_list args;
vscanf(out, &args[0]); // expected-no-warning@#f8
vprintf(out, &args[0]); // expected-no-warning@#f8
}
void f9(const char out[], ... /* args */) // #f9
{
va_list args;
char *ch;
vprintf(ch, args); // expected-no-warning
vsprintf(ch, out, args); // expected-warning@#f9 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f9'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 2)))"
}
void f10(const wchar_t *out, ... /* args */) // #f10
{
va_list args;
vscanf(out, args);
#if __SIZEOF_WCHAR_T__ == 4
// c_diagnostics-warning@-2 {{incompatible pointer types passing 'const wchar_t *' (aka 'const int *') to parameter of type 'const char *'}}
#else
// c_diagnostics-warning@-4 {{incompatible pointer types passing 'const wchar_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
#endif
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// c_diagnostics-warning@#f10 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f10'}}
// cpp_diagnostics-error@-8 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const wchar_t *' to 'const char *' for 1st argument}}
// C-CHECK: fix-it:"{{.*}}":{[[@LINE-13]]:6-[[@LINE-13]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
void f11(const wchar_t *out, ... /* args */) // #f11
{
va_list args;
vscanf((const char *) out, args); // expected-warning@#f11 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f11'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
void f12(const wchar_t *out, ... /* args */) // #f12
{
va_list args;
vscanf((char *) out, args); // expected-warning@#f12 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f12'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
void f13(const wchar_t *out, ... /* args */) // #f13
{
va_list args;
vscanf(out, args);
#if __SIZEOF_WCHAR_T__ == 4
// c_diagnostics-warning@-2 {{incompatible pointer types passing 'const wchar_t *' (aka 'const int *') to parameter of type 'const char *'}}
#else
// c_diagnostics-warning@-4 {{incompatible pointer types passing 'const wchar_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
#endif
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// cpp_diagnostics-error@-7 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const wchar_t *' to 'const char *' for 1st argument}}
// expected-warning@#f13 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f13'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-13]]:6-[[@LINE-13]]:6}:"__attribute__((format(scanf, 1, 2)))"
vscanf((const char *) out, args);
vscanf((char *) out, args);
}
void f14(const char *out) // #f14
{
va_list args;
vscanf(out, args); // expected-warning@#f14 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f14'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 0)))"
}
void f15(const char16_t *out, ... /* args */) // #f15
{
va_list args;
vscanf(out, args); // c_diagnostics-warning {{incompatible pointer types passing 'const char16_t *' (aka 'const unsigned short *') to parameter of type 'const char *'}}
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// c_diagnostics-warning@#f15 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f15'}}
// C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
// cpp_diagnostics-error@-4 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const char16_t *' to 'const char *' for 1st argument}}
}
void f16(const char32_t *out, ... /* args */) // #f16
{
va_list args;
vscanf(out, args); // c_diagnostics-warning {{incompatible pointer types passing 'const char32_t *' (aka 'const unsigned int *') to parameter of type 'const char *'}}
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// c_diagnostics-warning@#f16 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f16'}}
// C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
// cpp_diagnostics-error@-4 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const char32_t *' to 'const char *' for 1st argument}}
}
void f17(const unsigned char *out, ... /* args */) // #f17
{
va_list args;
vscanf(out, args); // c_diagnostics-warning {{passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// c_diagnostics-warning@#f17 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f17'}}
// C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
// cpp_diagnostics-error@-4 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vprintf {{candidate function not viable: no known conversion from 'const unsigned char *' to 'const char *' for 1st argument}}
}
void f18(const unsigned char *out, ... /* args */) // #f18
{
va_list args;
vscanf((const char *) out, args); // expected-warning@#f18 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f18'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
void f19(const unsigned char *out, ... /* args */) // #f19
{
va_list args;
vscanf((char *) out, args); // expected-warning@#f19 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f19'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
__attribute__((format(printf, 1, 2)))
void f20(const unsigned char *out, ... /* args */) // #f20
{
va_list args;
vprintf(out, args); // c_diagnostics-warning {{passing 'const unsigned char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}}
// c_diagnostics-note@#vprintf {{passing argument to parameter here}}
// cpp_diagnostics-error@-2 {{no matching function for call to 'vprintf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'const unsigned char *' to 'const char *' for 1st argument}}
vscanf((const char *) out, args); // expected-no-warning
vprintf((const char *) out, args); // expected-no-warning
vscanf((char *) out, args); // expected-no-warning
vprintf((char *) out, args); // expected-no-warning
}
void f21(signed char *out, ... /* args */) // #f21
{
va_list args;
vscanf(out, args); // c_diagnostics-warning {{passing 'signed char *' to parameter of type 'const char *' converts between pointers to integer types where one is of the unique plain 'char' type and the other is not}} \
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// c_diagnostics-warning@#f21 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f21'}}
// C-CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(scanf, 1, 2)))"
// cpp_diagnostics-error@-4 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'signed char *' to 'const char *' for 1st argument}}
}
void f22(signed char *out, ... /* args */) // #f22
{
va_list args;
vscanf((const char *) out, args); // expected-warning@#f22 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f22'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 2)))"
}
void f23(signed char *out, ... /* args */) // #f23
{
va_list args;
vprintf((char *) out, args); // expected-warning@#f23 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f23'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 2)))"
}
__attribute__((format(scanf, 1, 2)))
void f24(signed char *out, ... /* args */) // #f24
{
va_list args;
vprintf((const char *) out, args); // expected-no-warning@#f24
vprintf((char *) out, args); // expected-no-warning@#f24
}
__attribute__((format(printf, 1, 2)))
void f25(unsigned char out[], ... /* args */) // #f25
{
va_list args;
vscanf((const char *) out, args); // expected-no-warning@#f25
vscanf((char *) out, args); // expected-no-warning@#f25
}
void f26(char* out) // #f26
{
va_list args;
const char* ch;
vsprintf(out, ch, args); // expected-no-warning@#f26
vprintf(out, args); // expected-warning@#f26 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f26'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-6]]:6-[[@LINE-6]]:6}:"__attribute__((format(printf, 1, 0)))"
}
void f27(const char *out, ... /* args */) // #f27
{
int a;
printf(out, a); // expected-warning@#f27 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f27'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 0)))"
}
void f28(const char *out, ... /* args */) // #f28
{
printf(out, 1); // expected-warning@#f28 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f28'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(printf, 1, 0)))"
}
__attribute__((format(printf, 1, 2)))
void f29(const char *out, ... /* args */) // #f29
{
int a;
printf(out, a); // expected-no-warning@#f29
}
__attribute__((format(printf, 1, 2)))
void f30(const char *out, ... /* args */) // #f30
{
printf(out, 1); // expected-no-warning@#f30
}
__attribute__((format(printf, 1, 2)))
void f31(const char *out, ... /* args */) // #f31
{
int a;
printf(out, a); // expected-no-warning@#f31
printf(out, 1); // expected-no-warning@#f31
}
void f32(char *out, ... /* args */) // #f32
{
va_list args;
scanf(out, args); // expected-no-warning@#f32
{
printf(out, args); // expected-no-warning@#f32
}
}
void f33(char *out, va_list args) // #f33
{
{
scanf(out, args); // expected-no-warning@#f33
printf(out, args); // expected-no-warning@#f33
}
}
// expected-warning@#f34 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f34'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE+1]]:6-[[@LINE+1]]:6}:"__attribute__((format(scanf, 1, 2)))"
void f34(char *out, ... /* args */) // #f34
{
va_list args;
scanf(out, args); // expected-no-warning@#f34
{
scanf(out, args); // expected-no-warning@#f34
}
}
void f35(char* ch, const char *out, ... /* args */) // #f35
{
va_list args;
printf(ch, args); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 3)))"
int a;
printf(out, a); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-7]]:6-[[@LINE-7]]:6}:"__attribute__((format(printf, 2, 0)))"
printf(out, 1); // no warning because first command above emitted same warning with same fix-it text
printf(out, args); // expected-warning@#f35 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f35'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-10]]:6-[[@LINE-10]]:6}:"__attribute__((format(printf, 2, 3)))"
}
typedef va_list tdVaList;
typedef int tdInt;
void f36(const char *out, ... /* args */) // #f36
{
tdVaList args;
printf(out, args); // expected-warning@#f36 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f36'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 2)))"
}
void f37(const char *out, ... /* args */) // #f37
{
tdInt a;
scanf(out, a); // expected-warning@#f37 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f37'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(scanf, 1, 0)))"
}
void f38(const char *out, tdVaList args) // #f38
{
scanf(out, args); // expected-warning@#f38 {{diagnostic behavior may be improved by adding the 'scanf' format attribute to the declaration of 'f38'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:6-[[@LINE-3]]:6}:"__attribute__((format(scanf, 1, 0)))"
}
void f39(const char *out, tdVaList args) // #f39
{
tdInt a;
printf(out, a); // expected-warning@#f39 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f39'}}
// CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:6-[[@LINE-4]]:6}:"__attribute__((format(printf, 1, 0)))"
}
void f40(char *out, ... /* args */) // #f40
{
va_list args;
char *ch;
vscanf(ch, args); // expected-no-warning@#f40
vprintf(out, args); // expected-no-warning@#f40
}
void f41(char *out, ... /* args */) // #f41
{
va_list args;
char *ch;
vscanf("%s", ch);
#if defined(__x86_64__) && defined(__linux__)
// c_diagnostics-warning@-2 {{incompatible pointer types passing 'char *' to parameter of type 'struct __va_list_tag *'}}
// c_diagnostics-note@#vscanf {{passing argument to parameter here}}
// cpp_diagnostics-error@-4 {{no matching function for call to 'vscanf'}}
// cpp_diagnostics-note@#vscanf {{candidate function not viable: no known conversion from 'char *' to '__va_list_tag *' for 2nd argument}}
#endif
vprintf(out, args);
#if defined(__x86_64__) && defined(__linux__)
// cpp_diagnostics-warning@#f41 {{diagnostic behavior may be improved by adding the 'printf' format attribute to the declaration of 'f41'}}
// CHECK-LIN64: fix-it:"{{.*}}":{[[@LINE-14]]:6-[[@LINE-14]]:6}:"__attribute__((format(printf, 1, 2)))"
#endif
}