brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.7 KiB · 22c1cce Raw
308 lines · c
1// RUN: %clang_cc1 -std=c11 -fsyntax-only -verify -Wformat-nonliteral %s2 3// Test that -Wformat=0 works:4// RUN: %clang_cc1 -std=c11 -fsyntax-only -Werror -Wformat=0 %s5 6#include <stdarg.h>7typedef __SIZE_TYPE__ size_t;8#define __SSIZE_TYPE__                                                         \9  __typeof__(_Generic((__SIZE_TYPE__)0,                                        \10                      unsigned long long int : (long long int)0,               \11                      unsigned long int : (long int)0,                         \12                      unsigned int : (int)0,                                   \13                      unsigned short : (short)0,                               \14                      unsigned char : (signed char)0))15typedef __SSIZE_TYPE__ ssize_t;16 17typedef __PTRDIFF_TYPE__ ptrdiff_t;18#define __UNSIGNED_PTRDIFF_TYPE__                                              \19  __typeof__(_Generic((__PTRDIFF_TYPE__)0,                                     \20                      long long int : (unsigned long long int)0,               \21                      long int : (unsigned long int)0,                         \22                      int : (unsigned int)0,                                   \23                      short : (unsigned short)0,                               \24                      signed char : (unsigned char)0))25 26typedef struct _FILE FILE;27typedef __WCHAR_TYPE__ wchar_t;28 29int fscanf(FILE * restrict, const char * restrict, ...) ;30int scanf(const char * restrict, ...) ;31int sscanf(const char * restrict, const char * restrict, ...) ;32int my_scanf(const char * restrict, ...) __attribute__((__format__(__scanf__, 1, 2)));33int my_gnu_scanf(const char * restrict, ...) __attribute__((__format__(gnu_scanf, 1, 2)));34 35int vscanf(const char * restrict, va_list);36int vfscanf(FILE * restrict, const char * restrict, va_list);37int vsscanf(const char * restrict, const char * restrict, va_list);38 39void test(const char *s, int *i) {40  scanf(s, i); // expected-warning{{format string is not a string literal}}41  scanf("%0d", i); // expected-warning{{zero field width in scanf format string is unused}}42  scanf("%00d", i); // expected-warning{{zero field width in scanf format string is unused}}43  scanf("%d%[asdfasdfd", i, s); // expected-warning{{no closing ']' for '%[' in scanf format string}}44  scanf("%B", i); // expected-warning{{invalid conversion specifier 'B'}}45 46  unsigned short s_x;47  scanf ("%" "hu" "\n", &s_x); // no-warning48  scanf("%hb", &s_x);49  scanf("%y", i); // expected-warning{{invalid conversion specifier 'y'}}50  scanf("%%"); // no-warning51  scanf("%%%1$d", i); // no-warning52  scanf("%1$d%%", i); // no-warning53  scanf("%d", i, i); // expected-warning{{data argument not used by format string}}54  scanf("%*d", i); // // expected-warning{{data argument not used by format string}}55  scanf("%*d", i); // // expected-warning{{data argument not used by format string}}56  scanf("%*d%1$d", i); // no-warning57 58  scanf("%s", (char*)0); // no-warning59  scanf("%s", (volatile char*)0); // no-warning60  scanf("%s", (signed char*)0); // no-warning61  scanf("%s", (unsigned char*)0); // no-warning62  scanf("%hhu", (signed char*)0); // no-warning63  scanf("%hhb", (signed char*)0); // no-warning64}65 66void bad_length_modifiers(char *s, void *p, wchar_t *ws, long double *ld) {67  scanf("%hhs", "foo"); // expected-warning{{length modifier 'hh' results in undefined behavior or no effect with 's' conversion specifier}}68  scanf("%1$zp", &p); // expected-warning{{length modifier 'z' results in undefined behavior or no effect with 'p' conversion specifier}}69  scanf("%ls", ws); // no-warning70  scanf("%#.2Lf", ld); // expected-warning{{invalid conversion specifier '#'}}71}72 73void missing_argument_with_length_modifier() {74  char buf[30];75  scanf("%s:%900s", buf); // expected-warning{{more '%' conversions than data arguments}}76}77 78// Test that the scanf call site is where the warning is attached.  If the79// format string is somewhere else, point to it in a note.80void pr9751(void) {81  int *i;82  char str[100];83  const char kFormat1[] = "%00d"; // expected-note{{format string is defined here}}}84  scanf(kFormat1, i); // expected-warning{{zero field width in scanf format string is unused}}85  scanf("%00d", i); // expected-warning{{zero field width in scanf format string is unused}}86  const char kFormat2[] = "%["; // expected-note{{format string is defined here}}}87  scanf(kFormat2, str); // expected-warning{{no closing ']' for '%[' in scanf format string}}88  scanf("%[", str); // expected-warning{{no closing ']' for '%[' in scanf format string}}89  const char kFormat3[] = "%hu"; // expected-note{{format string is defined here}}}90  scanf(kFormat3, &i); // expected-warning {{format specifies type 'unsigned short *' but the argument}}91  const char kFormat4[] = "%lp"; // expected-note{{format string is defined here}}}92  scanf(kFormat4, &i); // expected-warning {{length modifier 'l' results in undefined behavior or no effect with 'p' conversion specifier}}93}94 95void test_variants(int *i, const char *s, ...) {96  FILE *f = 0;97  char buf[100];98 99  fscanf(f, "%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}100  sscanf(buf, "%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}101  my_scanf("%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}102  my_gnu_scanf("%ld", i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}103 104  va_list ap;105  va_start(ap, s);106 107  vscanf("%[abc", ap); // expected-warning{{no closing ']' for '%[' in scanf format string}}108  vfscanf(f, "%[abc", ap); // expected-warning{{no closing ']' for '%[' in scanf format string}}109  vsscanf(buf, "%[abc", ap); // expected-warning{{no closing ']' for '%[' in scanf format string}}110}111 112void test_scanlist(int *ip, char *sp, wchar_t *ls) {113  scanf("%[abc]", ip); // expected-warning{{format specifies type 'char *' but the argument has type 'int *'}}114  scanf("%h[abc]", sp); // expected-warning{{length modifier 'h' results in undefined behavior or no effect with '[' conversion specifier}}115  scanf("%l[xyx]", ls); // no-warning116  scanf("%ll[xyx]", ls); // expected-warning {{length modifier 'll' results in undefined behavior or no effect with '[' conversion specifier}}117 118  // PR19559119  scanf("%[]% ]", sp); // no-warning120  scanf("%[^]% ]", sp); // no-warning121  scanf("%[a^]% ]", sp); // expected-warning {{invalid conversion specifier ' '}}122}123 124void test_alloc_extension(char **sp, wchar_t **lsp, float *fp) {125  /* Make sure "%a" gets parsed as a conversion specifier for float,126   * even when followed by an 's', 'S' or '[', which would cause it to be127   * parsed as a length modifier in C90. */128  scanf("%as", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}}129  scanf("%aS", lsp); // expected-warning{{format specifies type 'float *' but the argument has type 'wchar_t **'}}130  scanf("%a[bcd]", sp); // expected-warning{{format specifies type 'float *' but the argument has type 'char **'}}131 132  // Test that the 'm' length modifier is only allowed with s, S, c, C or [.133  // TODO: Warn that 'm' is an extension.134  scanf("%ms", sp); // No warning.135  scanf("%mS", lsp); // No warning.136  scanf("%mc", sp); // No warning.137  scanf("%mC", lsp); // No warning.138  scanf("%m[abc]", sp); // No warning.139  scanf("%md", sp); // expected-warning{{length modifier 'm' results in undefined behavior or no effect with 'd' conversion specifier}}140 141  // Test argument type check for the 'm' length modifier.142  scanf("%ms", fp); // expected-warning{{format specifies type 'char **' but the argument has type 'float *'}}143  scanf("%mS", fp); // expected-warning-re{{format specifies type 'wchar_t **' (aka '{{[^']+}}') but the argument has type 'float *'}}144  scanf("%mc", fp); // expected-warning{{format specifies type 'char **' but the argument has type 'float *'}}145  scanf("%mC", fp); // expected-warning-re{{format specifies type 'wchar_t **' (aka '{{[^']+}}') but the argument has type 'float *'}}146  scanf("%m[abc]", fp); // expected-warning{{format specifies type 'char **' but the argument has type 'float *'}}147}148 149void test_quad(int *x, long long *llx) {150  scanf("%qd", x); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}151  scanf("%qd", llx); // no-warning152}153 154void test_writeback(int *x) {155  scanf("%n", (void*)0); // expected-warning{{format specifies type 'int *' but the argument has type 'void *'}}156  scanf("%n %c", x, x); // expected-warning{{format specifies type 'char *' but the argument has type 'int *'}}157 158  scanf("%hhn", (signed char*)0); // no-warning159  scanf("%hhn", (char*)0); // no-warning160  scanf("%hhn", (unsigned char*)0); // no-warning161  scanf("%hhn", (int*)0); // expected-warning{{format specifies type 'signed char *' but the argument has type 'int *'}}162 163  scanf("%hn", (short*)0); // no-warning164  scanf("%hn", (unsigned short*)0); // no-warning165  scanf("%hn", (int*)0); // expected-warning{{format specifies type 'short *' but the argument has type 'int *'}}166 167  scanf("%n", (int*)0); // no-warning168  scanf("%n", (unsigned int*)0); // no-warning169  scanf("%n", (char*)0); // expected-warning{{format specifies type 'int *' but the argument has type 'char *'}}170 171  scanf("%ln", (long*)0); // no-warning172  scanf("%ln", (unsigned long*)0); // no-warning173  scanf("%ln", (int*)0); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}174 175  scanf("%lln", (long long*)0); // no-warning176  scanf("%lln", (unsigned long long*)0); // no-warning177  scanf("%lln", (int*)0); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}178 179  scanf("%qn", (long long*)0); // no-warning180  scanf("%qn", (unsigned long long*)0); // no-warning181  scanf("%qn", (int*)0); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}182 183}184 185void test_qualifiers(const int *cip, volatile int* vip,186                     const char *ccp, volatile char* vcp,187                     const volatile int *cvip) {188  scanf("%d", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}189  scanf("%n", cip); // expected-warning{{format specifies type 'int *' but the argument has type 'const int *'}}190  scanf("%s", ccp); // expected-warning{{format specifies type 'char *' but the argument has type 'const char *'}}191  scanf("%d", cvip); // expected-warning{{format specifies type 'int *' but the argument has type 'const volatile int *'}}192 193  scanf("%d", vip); // No warning.194  scanf("%n", vip); // No warning.195  scanf("%c", vcp); // No warning.196 197  typedef int* ip_t;198  typedef const int* cip_t;199  scanf("%d", (ip_t)0); // No warning.200  scanf("%d", (cip_t)0); // expected-warning{{format specifies type 'int *' but the argument has type 'cip_t' (aka 'const int *')}}201}202 203void test_size_types(void) {204  size_t s = 0;205  scanf("%zu", &s); // No warning.206  scanf("%zb", &s);207 208  double d1 = 0.;209  scanf("%zu", &d1); // expected-warning-re{{format specifies type 'size_t *' (aka '{{.+}}') but the argument has type 'double *'}}210 211  ssize_t ss = 0;212  scanf("%zd", &s); // No warning.213 214  double d2 = 0.;215  scanf("%zd", &d2); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'double *'}}216 217  ssize_t sn = 0;218  scanf("%zn", &sn); // No warning.219 220  double d3 = 0.;221  scanf("%zn", &d3); // expected-warning-re{{format specifies type 'signed size_t *' (aka '{{.+}}') but the argument has type 'double *'}}222}223 224void test_ptrdiff_t_types(void) {225  __UNSIGNED_PTRDIFF_TYPE__ p1 = 0;226  scanf("%tu", &p1); // No warning.227  scanf("%tb", &p1);228 229  double d1 = 0.;230  scanf("%tu", &d1); // expected-warning-re{{format specifies type 'unsigned ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}231 232  ptrdiff_t p2 = 0;233  scanf("%td", &p2); // No warning.234 235  double d2 = 0.;236  scanf("%td", &d2); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}237 238  ptrdiff_t p3 = 0;239  scanf("%tn", &p3); // No warning.240 241  double d3 = 0.;242  scanf("%tn", &d3); // expected-warning-re{{format specifies type 'ptrdiff_t *' (aka '{{.+}}') but the argument has type 'double *'}}243}244 245void check_conditional_literal(char *s, int *i) {246  scanf(0 ? "%s" : "%d", i); // no warning247  scanf(1 ? "%s" : "%d", i); // expected-warning{{format specifies type 'char *'}}248  scanf(0 ? "%d %d" : "%d", i); // no warning249  scanf(1 ? "%d %d" : "%d", i); // expected-warning{{more '%' conversions than data arguments}}250  scanf(0 ? "%d %d" : "%d", i, s); // expected-warning{{data argument not used}}251  scanf(1 ? "%d %s" : "%d", i, s); // no warning252  scanf(i ? "%d %s" : "%d", i, s); // no warning253  scanf(i ? "%d" : "%d", i, s); // expected-warning{{data argument not used}}254  scanf(i ? "%s" : "%d", s); // expected-warning{{format specifies type 'int *'}}255}256 257void test_promotion(void) {258  // No promotions for *scanf pointers clarified in N2562259  // https://github.com/llvm/llvm-project/issues/57102260  // N2562: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2562.pdf261  int i;262  signed char sc;263  unsigned char uc;264  short ss;265  unsigned short us;266 267  // pointers could not be "promoted"268  scanf("%hhd", &i); // expected-warning{{format specifies type 'char *' but the argument has type 'int *'}}269  scanf("%hd", &i); // expected-warning{{format specifies type 'short *' but the argument has type 'int *'}}270  scanf("%d", &i); // no-warning271  // char & uchar272  scanf("%hhd", &sc); // no-warning273  scanf("%hhd", &uc); // no-warning274  scanf("%hd", &sc); // expected-warning{{format specifies type 'short *' but the argument has type 'signed char *'}}275  scanf("%hd", &uc); // expected-warning{{format specifies type 'short *' but the argument has type 'unsigned char *'}}276  scanf("%d", &sc); // expected-warning{{format specifies type 'int *' but the argument has type 'signed char *'}}277  scanf("%d", &uc); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned char *'}}278  // short & ushort279  scanf("%hhd", &ss); // expected-warning{{format specifies type 'char *' but the argument has type 'short *'}}280  scanf("%hhd", &us); // expected-warning{{format specifies type 'char *' but the argument has type 'unsigned short *'}}281  scanf("%hd", &ss); // no-warning282  scanf("%hd", &us); // no-warning283  scanf("%d", &ss); // expected-warning{{format specifies type 'int *' but the argument has type 'short *'}}284  scanf("%d", &us); // expected-warning{{format specifies type 'int *' but the argument has type 'unsigned short *'}}285 286  // long types287  scanf("%ld", &i); // expected-warning{{format specifies type 'long *' but the argument has type 'int *'}}288  scanf("%lld", &i); // expected-warning{{format specifies type 'long long *' but the argument has type 'int *'}}289  scanf("%ld", &sc); // expected-warning{{format specifies type 'long *' but the argument has type 'signed char *'}}290  scanf("%lld", &sc); // expected-warning{{format specifies type 'long long *' but the argument has type 'signed char *'}}291  scanf("%ld", &uc); // expected-warning{{format specifies type 'long *' but the argument has type 'unsigned char *'}}292  scanf("%lld", &uc); // expected-warning{{format specifies type 'long long *' but the argument has type 'unsigned char *'}}293  scanf("%llx", &i); // expected-warning{{format specifies type 'unsigned long long *' but the argument has type 'int *'}}294 295  // ill-formed floats296  scanf("%hf", // expected-warning{{length modifier 'h' results in undefined behavior or no effect with 'f' conversion specifier}}297  &sc);298 299  // pointers in scanf300  scanf("%s", i); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}301 302  // FIXME: does this match what the C committee allows or should it be pedantically warned on?303  char c;304  void *vp;305  scanf("%hhd", &c); // Pedantic warning?306  scanf("%hhd", vp); // expected-warning{{format specifies type 'char *' but the argument has type 'void *'}}307}308