brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 48cf239 Raw
241 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks %s2// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -fblocks -std=c++98 %s3// RUN: %clang_cc1 -fsyntax-only -verify -Wformat-nonliteral -Wformat-non-iso -Wformat-pedantic -fblocks -std=c++11 %s4 5#include <stdarg.h>6 7extern "C" {8extern int scanf(const char *restrict, ...);9extern int printf(const char *restrict, ...);10extern int vprintf(const char *restrict, va_list);11}12 13void f(char **sp, float *fp) {14  scanf("%as", sp);15#if __cplusplus <= 199711L16  // expected-warning@-2 {{'a' length modifier is not supported by ISO C}}17#else18  // expected-warning@-4 {{format specifies type 'float *' but the argument has type 'char **'}}19#endif20 21  printf("%a", 1.0);22  scanf("%afoobar", fp);23}24 25void 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.30class Foo {31public: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 42void 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.53extern "C" {54  int test_null_format(const char *format, ...) __attribute__((__format__ (__printf__, 1, 2)));55#if __cplusplus >= 201103L56  // expected-note@-2 {{candidate function not viable: no known conversion from 'bool' to 'const char *' for 1st argument}}57#endif58}59 60void rdar8269537(const char *f)61{62  test_null_format(false);63#if __cplusplus <= 199711L64  // expected-warning@-2 {{null from a constant boolean}}65#else66  // expected-error@-4 {{no matching function for call to 'test_null_format'}}67#endif68  test_null_format(0); // no-warning69  test_null_format(__null); // no-warning70  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 74int 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-warning79 80  const char *format2 = fmt;81  vprintf(format2, ap); // expected-warning{{format string is not a string literal}}82 83  return 0;84}85 86int 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 95namespace Templates {96  template<typename T>97  void my_uninstantiated_print(const T &arg) {98    printf("%d", arg); // no-warning99  }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-warning116    }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-warning139  }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 151namespace implicit_this_tests {152struct 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 159void 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#if __cplusplus >= 201103L167namespace evaluated {168 169constexpr const char *basic() { 170  return 171"%s %d"; // expected-note {{format string is defined here}}172}173 174constexpr const char *correct_fmt() { 175  return 176"%d %d";177}178 179constexpr const char *string_linebreak() { 180  return 181"%d %d"182"%d %s"; // expected-note {{format string is defined here}}183}184 185/*non-constexpr*/ const char *not_literal() { 186  return 187"%d %d"188"%d %s";189}190 191constexpr const char *inner_call() {192  return "%d %s"; // expected-note {{format string is defined here}}193}194 195constexpr const char *wrap_constexpr() {196  return inner_call();197}198 199 200void f() {201  printf(basic(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}202  printf(correct_fmt(), 1, 2);203  printf(string_linebreak(), 1, 2, 3, 4); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}204  printf(not_literal(), 1, 2, 3, 4); // expected-warning {{format string is not a string literal}}205  printf(wrap_constexpr(), 1, 2); // expected-warning {{format specifies type 'char *' but the argument has type 'int'}}206 207  constexpr const char *fmt {"%d%d"};208  printf(fmt, 1, 1); // no-warning209 210  constexpr const char *fmt2 {"%d"}; // expected-note{{format string is defined here}}211  printf(fmt2, "oops"); // expected-warning{{format specifies type 'int' but the argument has type}}212}213 214 215}216 217namespace ScopedEnumerations {218enum class Scoped1 { One };219enum class Scoped2 : unsigned short { Two };220 221void f(Scoped1 S1, Scoped2 S2) {222  printf("%hhd", S1); // expected-warning {{format specifies type 'char' but the argument has type 'Scoped1'}}223  printf("%hd", S1);  // expected-warning {{format specifies type 'short' but the argument has type 'Scoped1'}}224  printf("%d", S1);   // expected-warning {{format specifies type 'int' but the argument has type 'Scoped1'}}225 226  printf("%hhd", S2); // expected-warning {{format specifies type 'char' but the argument has type 'Scoped2'}}227  printf("%hd", S2);  // expected-warning {{format specifies type 'short' but the argument has type 'Scoped2'}}228  printf("%d", S2);   // expected-warning {{format specifies type 'int' but the argument has type 'Scoped2'}}229 230  scanf("%hhd", &S1); // expected-warning {{format specifies type 'char *' but the argument has type 'Scoped1 *'}}231  scanf("%hd", &S1);  // expected-warning {{format specifies type 'short *' but the argument has type 'Scoped1 *'}}232  scanf("%d", &S1);  // expected-warning {{format specifies type 'int *' but the argument has type 'Scoped1 *'}}233 234  scanf("%hhd", &S2); // expected-warning {{format specifies type 'char *' but the argument has type 'Scoped2 *'}}235  scanf("%hd", &S2);  // expected-warning {{format specifies type 'short *' but the argument has type 'Scoped2 *'}}236  scanf("%d", &S2);  // expected-warning {{format specifies type 'int *' but the argument has type 'Scoped2 *'}}237}238}239 240#endif241