Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection -analyzer-constraints=range -verify %s
      2 
      3 void clang_analyzer_eval(int);
      4 
      5 int string_literal_init() {
      6   char a[] = "abc";
      7   char b[2] = "abc"; // expected-warning{{too long}}
      8   char c[5] = "abc";
      9 
     10   clang_analyzer_eval(a[1] == 'b'); // expected-warning{{TRUE}}
     11   clang_analyzer_eval(b[1] == 'b'); // expected-warning{{TRUE}}
     12   clang_analyzer_eval(c[1] == 'b'); // expected-warning{{TRUE}}
     13 
     14   clang_analyzer_eval(a[3] == 0); // expected-warning{{TRUE}}
     15   clang_analyzer_eval(c[3] == 0); // expected-warning{{TRUE}}
     16 
     17   clang_analyzer_eval(c[4] == 0); // expected-warning{{TRUE}}
     18 
     19   return 42;
     20 }
     21 
     22 void nested_compound_literals(int rad) {
     23   int vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},  // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}}
     24                    {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}}; // expected-warning 6 {{implicit conversion from 'double' to 'int' changes value from}}
     25   int a;
     26 
     27   for (a = 0; a < 6; ++a) {
     28       vec[a][0] *= rad; // no-warning
     29       vec[a][1] *= rad; // no-warning
     30   }
     31 }
     32 
     33 void nested_compound_literals_float(float rad) {
     34   float vec[6][2] = {{0.195, 0.02}, {0.383, 0.067}, {0.55, 0.169},
     35                      {0.831, 0.45}, {0.924, 0.617}, {0.98, 0.805}};
     36   int a;
     37 
     38   for (a = 0; a < 6; ++a) {
     39       vec[a][0] *= rad; // no-warning
     40       vec[a][1] *= rad; // no-warning
     41   }
     42 }
     43 
     44 
     45 void struct_as_array() {
     46   struct simple { int x; int y; };
     47   struct simple a;
     48   struct simple *p = &a;
     49 
     50   p->x = 5;
     51   clang_analyzer_eval(a.x == 5); // expected-warning{{TRUE}}
     52   clang_analyzer_eval(p[0].x == 5); // expected-warning{{TRUE}}
     53 
     54   p[0].y = 5;
     55   clang_analyzer_eval(a.y == 5); // expected-warning{{TRUE}}
     56   clang_analyzer_eval(p->y == 5); // expected-warning{{TRUE}}
     57 }
     58 
     59 
     60 // PR13264 / <rdar://problem/11802440>
     61 struct point { int x; int y; };
     62 struct circle { struct point o; int r; };
     63 struct circle get_circle() {
     64   struct circle result;
     65   result.r = 5;
     66   result.o = (struct point){0, 0};
     67   return result;
     68 }
     69 
     70 void struct_in_struct() {
     71   struct circle c;
     72   c = get_circle();
     73   // This used to think c.r was undefined because c.o is a LazyCompoundVal.
     74   clang_analyzer_eval(c.r == 5); // expected-warning{{TRUE}}
     75 }
     76 
     77 // We also test with floats because we don't model floats right now,
     78 // and the original bug report used a float.
     79 struct circle_f { struct point o; float r; };
     80 struct circle_f get_circle_f() {
     81   struct circle_f result;
     82   result.r = 5.0;
     83   result.o = (struct point){0, 0};
     84   return result;
     85 }
     86 
     87 float struct_in_struct_f() {
     88   struct circle_f c;
     89   c = get_circle_f();
     90 
     91   return c.r; // no-warning
     92 }
     93 
     94 
     95 int randomInt();
     96 
     97 int testSymbolicInvalidation(int index) {
     98   int vals[10];
     99 
    100   vals[0] = 42;
    101   clang_analyzer_eval(vals[0] == 42); // expected-warning{{TRUE}}
    102 
    103   vals[index] = randomInt();
    104   clang_analyzer_eval(vals[0] == 42); // expected-warning{{UNKNOWN}}
    105 
    106   return vals[index]; // no-warning
    107 }
    108 
    109 int testConcreteInvalidation(int index) {
    110   int vals[10];
    111 
    112   vals[index] = 42;
    113   clang_analyzer_eval(vals[index] == 42); // expected-warning{{TRUE}}
    114   vals[0] = randomInt();
    115   clang_analyzer_eval(vals[index] == 42); // expected-warning{{UNKNOWN}}
    116 
    117   return vals[0]; // no-warning
    118 }
    119 
    120 
    121 typedef struct {
    122   int x, y, z;
    123 } S;
    124 
    125 S makeS();
    126 
    127 int testSymbolicInvalidationStruct(int index) {
    128   S vals[10];
    129 
    130   vals[0].x = 42;
    131   clang_analyzer_eval(vals[0].x == 42); // expected-warning{{TRUE}}
    132 
    133   vals[index] = makeS();
    134   clang_analyzer_eval(vals[0].x == 42); // expected-warning{{UNKNOWN}}
    135 
    136   return vals[index].x; // no-warning
    137 }
    138 
    139 int testConcreteInvalidationStruct(int index) {
    140   S vals[10];
    141 
    142   vals[index].x = 42;
    143   clang_analyzer_eval(vals[index].x == 42); // expected-warning{{TRUE}}
    144   vals[0] = makeS();
    145   clang_analyzer_eval(vals[index].x == 42); // expected-warning{{UNKNOWN}}
    146 
    147   return vals[0].x; // no-warning
    148 }
    149 
    150 typedef struct {
    151   S a[5];
    152   S b[5];
    153 } SS;
    154 
    155 int testSymbolicInvalidationDoubleStruct(int index) {
    156   SS vals;
    157 
    158   vals.a[0].x = 42;
    159   vals.b[0].x = 42;
    160   clang_analyzer_eval(vals.a[0].x == 42); // expected-warning{{TRUE}}
    161   clang_analyzer_eval(vals.b[0].x == 42); // expected-warning{{TRUE}}
    162 
    163   vals.a[index] = makeS();
    164   clang_analyzer_eval(vals.a[0].x == 42); // expected-warning{{UNKNOWN}}
    165   clang_analyzer_eval(vals.b[0].x == 42); // expected-warning{{TRUE}}
    166 
    167   return vals.b[index].x; // no-warning
    168 }
    169 
    170 int testConcreteInvalidationDoubleStruct(int index) {
    171   SS vals;
    172 
    173   vals.a[index].x = 42;
    174   vals.b[index].x = 42;
    175   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{TRUE}}
    176   clang_analyzer_eval(vals.b[index].x == 42); // expected-warning{{TRUE}}
    177 
    178   vals.a[0] = makeS();
    179   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
    180   clang_analyzer_eval(vals.b[index].x == 42); // expected-warning{{TRUE}}
    181 
    182   return vals.b[0].x; // no-warning
    183 }
    184 
    185 
    186 int testNonOverlappingStructFieldsSimple() {
    187   S val;
    188 
    189   val.x = 1;
    190   val.y = 2;
    191   clang_analyzer_eval(val.x == 1); // expected-warning{{TRUE}}
    192   clang_analyzer_eval(val.y == 2); // expected-warning{{TRUE}}
    193 
    194   return val.z; // expected-warning{{garbage}}
    195 }
    196 
    197 int testNonOverlappingStructFieldsSymbolicBase(int index, int anotherIndex) {
    198   SS vals;
    199 
    200   vals.a[index].x = 42;
    201   vals.a[index].y = 42;
    202   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{TRUE}}
    203   clang_analyzer_eval(vals.a[index].y == 42); // expected-warning{{TRUE}}
    204 
    205   vals.a[anotherIndex].x = 42;
    206   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
    207   clang_analyzer_eval(vals.a[index].y == 42); // expected-warning{{TRUE}}
    208 
    209   // FIXME: False negative. No bind ever set a field 'z'.
    210   return vals.a[index].z; // no-warning
    211 }
    212 
    213 int testStructFieldChains(int index, int anotherIndex) {
    214   SS vals[4];
    215 
    216   vals[index].a[0].x = 42;
    217   vals[anotherIndex].a[1].y = 42;
    218   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    219   clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
    220 
    221   // This doesn't affect anything in the 'a' array field.
    222   vals[anotherIndex].b[1].x = 42;
    223   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    224   clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
    225   clang_analyzer_eval(vals[anotherIndex].b[1].x == 42); // expected-warning{{TRUE}}
    226 
    227   // This doesn't affect anything in the 'b' array field.
    228   vals[index].a[anotherIndex].x = 42;
    229   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
    230   clang_analyzer_eval(vals[anotherIndex].a[0].x == 42); // expected-warning{{UNKNOWN}}
    231   clang_analyzer_eval(vals[anotherIndex].a[1].y == 42); // expected-warning{{TRUE}}
    232   clang_analyzer_eval(vals[anotherIndex].b[1].x == 42); // expected-warning{{TRUE}}
    233 
    234   // FIXME: False negative. No bind ever set a field 'z'.
    235   return vals[index].a[0].z; // no-warning
    236 }
    237 
    238 int testStructFieldChainsNested(int index, int anotherIndex) {
    239   SS vals[4];
    240 
    241   vals[index].a[0].x = 42;
    242   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    243 
    244   vals[index].b[0] = makeS();
    245   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    246 
    247   vals[index].a[0] = makeS();
    248   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
    249 
    250   vals[index].a[0].x = 42;
    251   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    252 
    253   return 0;
    254 }
    255 
    256 typedef struct {
    257   int zoomLevel;
    258   struct point center;
    259 } Outer;
    260 
    261 extern int test13116945(struct point x);
    262 static void radar13116945(struct point centerCoordinate) {
    263   Outer zoomRegion;
    264   zoomRegion.zoomLevel = 0;
    265   zoomRegion.center = centerCoordinate;
    266   Outer r = zoomRegion;
    267   test13116945(r.center); // no-warning
    268 }
    269 
    270 
    271 typedef struct {
    272   char data[4];
    273 } ShortString;
    274 
    275 typedef struct {
    276   ShortString str;
    277   int length;
    278 } ShortStringWrapper;
    279 
    280 void testArrayStructCopy() {
    281   ShortString s = { "abc" };
    282   ShortString s2 = s;
    283   ShortString s3 = s2;
    284 
    285   clang_analyzer_eval(s3.data[0] == 'a'); // expected-warning{{TRUE}}
    286   clang_analyzer_eval(s3.data[1] == 'b'); // expected-warning{{TRUE}}
    287   clang_analyzer_eval(s3.data[2] == 'c'); // expected-warning{{TRUE}}
    288 
    289   s3.data[0] = 'z';
    290   ShortString s4 = s3;
    291 
    292   clang_analyzer_eval(s4.data[0] == 'z'); // expected-warning{{TRUE}}
    293   clang_analyzer_eval(s4.data[1] == 'b'); // expected-warning{{TRUE}}
    294   clang_analyzer_eval(s4.data[2] == 'c'); // expected-warning{{TRUE}}
    295 }
    296 
    297 void testArrayStructCopyNested() {
    298   ShortString s = { "abc" };
    299   ShortString s2 = s;
    300 
    301   ShortStringWrapper w = { s2, 0 };
    302 
    303   clang_analyzer_eval(w.str.data[0] == 'a'); // expected-warning{{TRUE}}
    304   clang_analyzer_eval(w.str.data[1] == 'b'); // expected-warning{{TRUE}}
    305   clang_analyzer_eval(w.str.data[2] == 'c'); // expected-warning{{TRUE}}
    306   clang_analyzer_eval(w.length == 0); // expected-warning{{TRUE}}
    307 
    308   ShortStringWrapper w2 = w;
    309   clang_analyzer_eval(w2.str.data[0] == 'a'); // expected-warning{{TRUE}}
    310   clang_analyzer_eval(w2.str.data[1] == 'b'); // expected-warning{{TRUE}}
    311   clang_analyzer_eval(w2.str.data[2] == 'c'); // expected-warning{{TRUE}}
    312   clang_analyzer_eval(w2.length == 0); // expected-warning{{TRUE}}
    313 
    314   ShortStringWrapper w3 = w2;
    315   clang_analyzer_eval(w3.str.data[0] == 'a'); // expected-warning{{TRUE}}
    316   clang_analyzer_eval(w3.str.data[1] == 'b'); // expected-warning{{TRUE}}
    317   clang_analyzer_eval(w3.str.data[2] == 'c'); // expected-warning{{TRUE}}
    318   clang_analyzer_eval(w3.length == 0); // expected-warning{{TRUE}}
    319 }
    320 
    321 // --------------------
    322 // False positives
    323 // --------------------
    324 
    325 int testMixSymbolicAndConcrete(int index, int anotherIndex) {
    326   SS vals;
    327 
    328   vals.a[index].x = 42;
    329   vals.a[0].y = 42;
    330 
    331   // FIXME: Should be TRUE.
    332   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
    333   // Should be TRUE; we set this explicitly.
    334   clang_analyzer_eval(vals.a[0].y == 42); // expected-warning{{TRUE}}
    335 
    336   vals.a[anotherIndex].y = 42;
    337 
    338   // Should be UNKNOWN; we set an 'x'.
    339   clang_analyzer_eval(vals.a[index].x == 42); // expected-warning{{UNKNOWN}}
    340   // FIXME: Should be TRUE.
    341   clang_analyzer_eval(vals.a[0].y == 42); // expected-warning{{UNKNOWN}}
    342 
    343   return vals.a[0].x; // no-warning
    344 }
    345 
    346 void testFieldChainIsNotEnough(int index) {
    347   SS vals[4];
    348 
    349   vals[index].a[0].x = 42;
    350   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{TRUE}}
    351 
    352   vals[index].a[1] = makeS();
    353   // FIXME: Should be TRUE.
    354   clang_analyzer_eval(vals[index].a[0].x == 42); // expected-warning{{UNKNOWN}}
    355 }
    356