Home | History | Annotate | Download | only in FixIt
      1 // RUN: %clang_cc1 -fsyntax-only -fblocks -verify %s
      2 // RUN: %clang_cc1 -fdiagnostics-parseable-fixits -fblocks %s 2>&1 | FileCheck %s
      3 
      4 @class NSString;
      5 extern void NSLog(NSString *, ...);
      6 int printf(const char * restrict, ...) ;
      7 
      8 void test_integer_correction (int x) {
      9   printf("%d", x); // no-warning
     10   printf("%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
     11   printf("%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
     12   // CHECK: fix-it:"{{.*}}":{10:11-10:13}:"%d"
     13   // CHECK: fix-it:"{{.*}}":{11:11-11:14}:"%d"
     14 
     15   NSLog(@"%d", x); // no-warning
     16   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
     17   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
     18   NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'int'}}
     19   // CHECK: fix-it:"{{.*}}":{16:11-16:13}:"%d"
     20   // CHECK: fix-it:"{{.*}}":{17:11-17:14}:"%d"
     21   // CHECK: fix-it:"{{.*}}":{18:11-18:13}:"%d"
     22 }
     23 
     24 void test_string_correction (char *x) {
     25   printf("%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
     26   printf("%s", x); // no-warning
     27   printf("%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'char *'}}
     28   // CHECK: fix-it:"{{.*}}":{25:11-25:13}:"%s"
     29   // CHECK: fix-it:"{{.*}}":{27:11-27:14}:"%s"
     30 
     31   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'char *'}}
     32   NSLog(@"%s", x); // no-warning
     33   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'char *'}}
     34   NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'char *'}}
     35   // CHECK: fix-it:"{{.*}}":{31:11-31:13}:"%s"
     36   // CHECK: fix-it:"{{.*}}":{33:11-33:14}:"%s"
     37   // CHECK: fix-it:"{{.*}}":{34:11-34:13}:"%s"
     38 }
     39 
     40 void test_object_correction (id x) {  
     41   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'id'}}
     42   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'id'}}
     43   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'id'}}
     44   NSLog(@"%@", x); // no-warning
     45   // CHECK: fix-it:"{{.*}}":{41:11-41:13}:"%@"
     46   // CHECK: fix-it:"{{.*}}":{42:11-42:13}:"%@"
     47   // CHECK: fix-it:"{{.*}}":{43:11-43:14}:"%@"
     48 }
     49 
     50 typedef const struct __CFString * __attribute__((NSObject)) CFStringRef;
     51 void test_cf_object_correction (CFStringRef x) {
     52   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'CFStringRef'}}
     53   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'CFStringRef'}}
     54   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'CFStringRef'}}
     55   NSLog(@"%@", x); // no-warning
     56   // CHECK: fix-it:"{{.*}}":{52:11-52:13}:"%@"
     57   // CHECK: fix-it:"{{.*}}":{53:11-53:13}:"%@"
     58   // CHECK: fix-it:"{{.*}}":{54:11-54:14}:"%@"
     59 }
     60 
     61 typedef void (^block_t)(void);
     62 void test_block_correction (block_t x) {
     63   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'block_t'}}
     64   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'block_t'}}
     65   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'block_t'}}
     66   NSLog(@"%@", x); // no-warning
     67   // CHECK: fix-it:"{{.*}}":{63:11-63:13}:"%@"
     68   // CHECK: fix-it:"{{.*}}":{64:11-64:13}:"%@"
     69   // CHECK: fix-it:"{{.*}}":{65:11-65:14}:"%@"
     70 }
     71 
     72 void test_class_correction (Class x) {
     73   NSLog(@"%d", x); // expected-warning{{format specifies type 'int' but the argument has type 'Class'}}
     74   NSLog(@"%s", x); // expected-warning{{format specifies type 'char *' but the argument has type 'Class'}}
     75   NSLog(@"%lf", x); // expected-warning{{format specifies type 'double' but the argument has type 'Class'}}
     76   NSLog(@"%@", x); // no-warning
     77   // CHECK: fix-it:"{{.*}}":{73:11-73:13}:"%@"
     78   // CHECK: fix-it:"{{.*}}":{74:11-74:13}:"%@"
     79   // CHECK: fix-it:"{{.*}}":{75:11-75:14}:"%@"
     80 }
     81 
     82 
     83 typedef enum : int { NSUTF8StringEncoding = 8 } NSStringEncoding;
     84 void test_fixed_enum_correction(NSStringEncoding x) {
     85   NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'NSStringEncoding'}}
     86   // CHECK: fix-it:"{{.*}}":{85:11-85:13}:"%d"
     87 }
     88 
     89 typedef __SIZE_TYPE__ size_t;
     90 enum SomeSize : size_t { IntegerSize = sizeof(int) };
     91 void test_named_fixed_enum_correction(enum SomeSize x) {
     92   NSLog(@"%@", x); // expected-warning{{format specifies type 'id' but the argument has type 'enum SomeSize'}}
     93   // CHECK: fix-it:"{{.*}}":{92:11-92:13}:"%zu"
     94 }
     95 
     96 
     97 typedef unsigned char uint8_t;
     98 void test_char(char c, signed char s, unsigned char u, uint8_t n) {
     99   NSLog(@"%s", c); // expected-warning{{format specifies type 'char *' but the argument has type 'char'}}
    100   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    101 
    102   NSLog(@"%lf", c); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
    103   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
    104 
    105   NSLog(@"%@", c); // expected-warning{{format specifies type 'id' but the argument has type 'char'}}
    106   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    107 
    108   NSLog(@"%c", c); // no-warning
    109   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    110 
    111   
    112   NSLog(@"%s", s); // expected-warning{{format specifies type 'char *' but the argument has type 'signed char'}}
    113   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    114 
    115   NSLog(@"%lf", s); // expected-warning{{format specifies type 'double' but the argument has type 'signed char'}}
    116   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
    117 
    118   NSLog(@"%@", s); // expected-warning{{format specifies type 'id' but the argument has type 'signed char'}}
    119   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    120 
    121   NSLog(@"%c", s); // no-warning
    122   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    123 
    124 
    125   NSLog(@"%s", u); // expected-warning{{format specifies type 'char *' but the argument has type 'unsigned char'}}
    126   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    127 
    128   NSLog(@"%lf", u); // expected-warning{{format specifies type 'double' but the argument has type 'unsigned char'}}
    129   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
    130 
    131   NSLog(@"%@", u); // expected-warning{{format specifies type 'id' but the argument has type 'unsigned char'}}
    132   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    133 
    134   NSLog(@"%c", u); // no-warning
    135   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    136 
    137 
    138   NSLog(@"%s", n); // expected-warning{{format specifies type 'char *' but the argument has type 'uint8_t' (aka 'unsigned char')}}
    139   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
    140 
    141   NSLog(@"%lf", n); // expected-warning{{format specifies type 'double' but the argument has type 'uint8_t' (aka 'unsigned char')}}
    142   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%hhu"
    143 
    144   NSLog(@"%@", n); // expected-warning{{format specifies type 'id' but the argument has type 'uint8_t' (aka 'unsigned char')}}
    145   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
    146 
    147   NSLog(@"%c", n); // no-warning
    148   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%hhu"
    149 
    150 
    151   NSLog(@"%s", 'a'); // expected-warning{{format specifies type 'char *' but the argument has type 'char'}}
    152   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    153 
    154   NSLog(@"%lf", 'a'); // expected-warning{{format specifies type 'double' but the argument has type 'char'}}
    155   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%c"
    156 
    157   NSLog(@"%@", 'a'); // expected-warning{{format specifies type 'id' but the argument has type 'char'}}
    158   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    159 
    160   NSLog(@"%c", 'a'); // no-warning
    161   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    162 
    163 
    164   NSLog(@"%s", 'abcd'); // expected-warning{{format specifies type 'char *' but the argument has type 'int'}}
    165   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    166 
    167   NSLog(@"%lf", 'abcd'); // expected-warning{{format specifies type 'double' but the argument has type 'int'}}
    168   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:14}:"%d"
    169 
    170   NSLog(@"%@", 'abcd'); // expected-warning{{format specifies type 'id' but the argument has type 'int'}}
    171   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    172 }
    173 
    174 void multichar_constants_false_negative() {
    175   // The value of a multi-character constant is implementation-defined, but
    176   // almost certainly shouldn't be printed with %c. However, the current
    177   // type-checker expects %c to correspond to an integer argument, because
    178   // many C library functions like fgetc() actually return an int (using -1
    179   // as a sentinel).
    180   NSLog(@"%c", 'abcd'); // missing-warning{{format specifies type 'char' but the argument has type 'int'}}
    181   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    182 }
    183 
    184 
    185 void test_percent_C() {
    186   const unsigned short data = 'a';
    187   NSLog(@"%C", data);  // no-warning
    188 
    189   NSLog(@"%C", 0x2603);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
    190   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    191   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unsigned short)"
    192 
    193   typedef unsigned short unichar;
    194   
    195   NSLog(@"%C", 0x2603);  // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
    196   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    197   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
    198   
    199   NSLog(@"%C", data ? 0x2F : 0x2603); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'int'}}
    200   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%d"
    201   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)("
    202   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:36-[[@LINE-3]]:36}:")"
    203 
    204   NSLog(@"%C", 0.0); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'double'}}
    205   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%f"
    206   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:16}:"(unichar)"
    207 
    208   NSLog(@"%C", (char)0x2603); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
    209   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    210   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:22}:"(unichar)"
    211 
    212   NSLog(@"%C", 'a'); // expected-warning{{format specifies type 'unichar' (aka 'unsigned short') but the argument has type 'char'}}
    213   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:13}:"%c"
    214   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-2]]:16-[[@LINE-2]]:22}:"(unichar)"
    215 }
    216 
    217 
    218 void testSignedness(long i, unsigned long u) {
    219   printf("%d", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
    220   printf("%i", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
    221   printf("%u", i); // expected-warning{{format specifies type 'unsigned int' but the argument has type 'long'}}
    222 
    223   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"
    224   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%lu"
    225   // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:11-[[@LINE-4]]:13}:"%ld"
    226 
    227   printf("%+d", u); // expected-warning{{format specifies type 'int' but the argument has type 'unsigned long'}}
    228 
    229   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:14}:"%+ld"
    230 }
    231