xref: /aosp_15_r20/external/clang/test/SemaCXX/format-strings.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks %s
2*67e74705SXin Li 
3*67e74705SXin Li #include <stdarg.h>
4*67e74705SXin Li 
5*67e74705SXin Li extern "C" {
6*67e74705SXin Li extern int scanf(const char *restrict, ...);
7*67e74705SXin Li extern int printf(const char *restrict, ...);
8*67e74705SXin Li extern int vprintf(const char *restrict, va_list);
9*67e74705SXin Li }
10*67e74705SXin Li 
f(char ** sp,float * fp)11*67e74705SXin Li void f(char **sp, float *fp) {
12*67e74705SXin Li   scanf("%as", sp); // expected-warning{{'a' length modifier is not supported by ISO C}}
13*67e74705SXin Li 
14*67e74705SXin Li   // TODO: Warn that the 'a' conversion specifier is a C++11 feature.
15*67e74705SXin Li   printf("%a", 1.0);
16*67e74705SXin Li   scanf("%afoobar", fp);
17*67e74705SXin Li }
18*67e74705SXin Li 
g()19*67e74705SXin Li void g() {
20*67e74705SXin Li   printf("%ls", "foo"); // expected-warning{{format specifies type 'wchar_t *' but the argument has type 'const char *'}}
21*67e74705SXin Li }
22*67e74705SXin Li 
23*67e74705SXin Li // Test that we properly handle format_idx on C++ members.
24*67e74705SXin Li class Foo {
25*67e74705SXin Li public:
26*67e74705SXin Li   const char *gettext(const char *fmt) __attribute__((format_arg(2)));
27*67e74705SXin Li 
28*67e74705SXin Li   int scanf(const char *, ...) __attribute__((format(scanf, 2, 3)));
29*67e74705SXin Li   int printf(const char *, ...) __attribute__((format(printf, 2, 3)));
30*67e74705SXin Li   int printf2(const char *, ...);
31*67e74705SXin Li 
32*67e74705SXin Li   static const char *gettext_static(const char *fmt) __attribute__((format_arg(1)));
33*67e74705SXin Li   static int printf_static(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
34*67e74705SXin Li };
35*67e74705SXin Li 
h(int * i)36*67e74705SXin Li void h(int *i) {
37*67e74705SXin Li   Foo foo;
38*67e74705SXin Li   foo.scanf("%d"); // expected-warning{{more '%' conversions than data arguments}}
39*67e74705SXin Li   foo.printf("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
40*67e74705SXin Li   Foo::printf_static("%d", i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
41*67e74705SXin Li 
42*67e74705SXin Li   printf(foo.gettext("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
43*67e74705SXin Li   printf(Foo::gettext_static("%d"), i); // expected-warning{{format specifies type 'int' but the argument has type 'int *'}}
44*67e74705SXin Li }
45*67e74705SXin Li 
46*67e74705SXin Li // Test handling __null for format string literal checking.
47*67e74705SXin Li extern "C" {
48*67e74705SXin Li   int test_null_format(const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));
49*67e74705SXin Li }
50*67e74705SXin Li 
rdar8269537(const char * f)51*67e74705SXin Li void rdar8269537(const char *f)
52*67e74705SXin Li {
53*67e74705SXin Li   test_null_format(false); // expected-warning {{null from a constant boolean}}
54*67e74705SXin Li   test_null_format(0); // no-warning
55*67e74705SXin Li   test_null_format(__null); // no-warning
56*67e74705SXin Li   test_null_format(f); // expected-warning {{not a string literal}}
57*67e74705SXin Li   // expected-note@-1{{treat the string as an argument to avoid this}}
58*67e74705SXin Li }
59*67e74705SXin Li 
printf(const char * fmt,...)60*67e74705SXin Li int Foo::printf(const char *fmt, ...) {
61*67e74705SXin Li   va_list ap;
62*67e74705SXin Li   va_start(ap,fmt);
63*67e74705SXin Li   const char * const format = fmt;
64*67e74705SXin Li   vprintf(format, ap); // no-warning
65*67e74705SXin Li 
66*67e74705SXin Li   const char *format2 = fmt;
67*67e74705SXin Li   vprintf(format2, ap); // expected-warning{{format string is not a string literal}}
68*67e74705SXin Li 
69*67e74705SXin Li   return 0;
70*67e74705SXin Li }
71*67e74705SXin Li 
printf2(const char * fmt,...)72*67e74705SXin Li int Foo::printf2(const char *fmt, ...) {
73*67e74705SXin Li   va_list ap;
74*67e74705SXin Li   va_start(ap,fmt);
75*67e74705SXin Li   vprintf(fmt, ap); // expected-warning{{format string is not a string literal}}
76*67e74705SXin Li 
77*67e74705SXin Li   return 0;
78*67e74705SXin Li }
79*67e74705SXin Li 
80*67e74705SXin Li 
81*67e74705SXin Li namespace Templates {
82*67e74705SXin Li   template<typename T>
my_uninstantiated_print(const T & arg)83*67e74705SXin Li   void my_uninstantiated_print(const T &arg) {
84*67e74705SXin Li     printf("%d", arg); // no-warning
85*67e74705SXin Li   }
86*67e74705SXin Li 
87*67e74705SXin Li   template<typename T>
my_print(const T & arg)88*67e74705SXin Li   void my_print(const T &arg) {
89*67e74705SXin Li     printf("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
90*67e74705SXin Li   }
91*67e74705SXin Li 
use_my_print()92*67e74705SXin Li   void use_my_print() {
93*67e74705SXin Li     my_print("abc"); // expected-note {{requested here}}
94*67e74705SXin Li   }
95*67e74705SXin Li 
96*67e74705SXin Li 
97*67e74705SXin Li   template<typename T>
98*67e74705SXin Li   class UninstantiatedPrinter {
99*67e74705SXin Li   public:
print(const T & arg)100*67e74705SXin Li     static void print(const T &arg) {
101*67e74705SXin Li       printf("%d", arg); // no-warning
102*67e74705SXin Li     }
103*67e74705SXin Li   };
104*67e74705SXin Li 
105*67e74705SXin Li   template<typename T>
106*67e74705SXin Li   class Printer {
107*67e74705SXin Li     void format(const char *fmt, ...) __attribute__((format(printf,2,3)));
108*67e74705SXin Li   public:
109*67e74705SXin Li 
print(const T & arg)110*67e74705SXin Li     void print(const T &arg) {
111*67e74705SXin Li       format("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
112*67e74705SXin Li     }
113*67e74705SXin Li   };
114*67e74705SXin Li 
use_class(Printer<const char * > & p)115*67e74705SXin Li   void use_class(Printer<const char *> &p) {
116*67e74705SXin Li     p.print("abc"); // expected-note {{requested here}}
117*67e74705SXin Li   }
118*67e74705SXin Li 
119*67e74705SXin Li 
120*67e74705SXin Li   extern void (^block_print)(const char * format, ...) __attribute__((format(printf, 1, 2)));
121*67e74705SXin Li 
122*67e74705SXin Li   template<typename T>
uninstantiated_call_block_print(const T & arg)123*67e74705SXin Li   void uninstantiated_call_block_print(const T &arg) {
124*67e74705SXin Li     block_print("%d", arg); // no-warning
125*67e74705SXin Li   }
126*67e74705SXin Li 
127*67e74705SXin Li   template<typename T>
call_block_print(const T & arg)128*67e74705SXin Li   void call_block_print(const T &arg) {
129*67e74705SXin Li     block_print("%d", arg); // expected-warning {{format specifies type 'int' but the argument has type 'const char *'}}
130*67e74705SXin Li   }
131*67e74705SXin Li 
use_block_print()132*67e74705SXin Li   void use_block_print() {
133*67e74705SXin Li     call_block_print("abc"); // expected-note {{requested here}}
134*67e74705SXin Li   }
135*67e74705SXin Li }
136*67e74705SXin Li 
137*67e74705SXin Li namespace implicit_this_tests {
138*67e74705SXin Li struct t {
139*67e74705SXin Li     void func1(const char *, ...) __attribute__((__format__(printf, 1, 2))); // expected-error {{format attribute cannot specify the implicit this argument as the format string}}
140*67e74705SXin Li     void (*func2)(const char *, ...) __attribute__((__format__(printf, 1, 2)));
141*67e74705SXin Li     static void (*func3)(const char *, ...) __attribute__((__format__(printf, 1, 2)));
142*67e74705SXin Li     static void func4(const char *, ...) __attribute__((__format__(printf, 1, 2)));
143*67e74705SXin Li };
144*67e74705SXin Li 
f()145*67e74705SXin Li void f() {
146*67e74705SXin Li   t t1;
147*67e74705SXin Li   t1.func2("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
148*67e74705SXin Li   t::func3("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
149*67e74705SXin Li   t::func4("Hello %s"); // expected-warning {{more '%' conversions than data arguments}}
150*67e74705SXin Li }
151*67e74705SXin Li }
152