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