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