Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core,debug.ExprInspection %s -analyzer-store=region -verify
      2 
      3 void clang_analyzer_eval(int);
      4 
      5 unsigned foo();
      6 typedef struct bf { unsigned x:2; } bf;
      7 void bar() {
      8   bf y;
      9   *(unsigned*)&y = foo();
     10   y.x = 1;
     11 }
     12 
     13 struct s {
     14   int n;
     15 };
     16 
     17 void f() {
     18   struct s a;
     19   int *p = &(a.n) + 1; // expected-warning{{Pointer arithmetic on}}
     20 }
     21 
     22 typedef struct {
     23   int x,y;
     24 } Point;
     25 
     26 Point getit(void);
     27 void test() {
     28   Point p;
     29   (void)(p = getit()).x;
     30 }
     31 
     32 #define true ((bool)1)
     33 #define false ((bool)0)
     34 typedef _Bool bool;
     35 
     36 
     37 void testLazyCompoundVal() {
     38   Point p = {42, 0};
     39   Point q;
     40   clang_analyzer_eval((q = p).x == 42); // expected-warning{{TRUE}}
     41   clang_analyzer_eval(q.x == 42); // expected-warning{{TRUE}}
     42 }
     43 
     44 
     45 struct Bits {
     46   unsigned a : 1;
     47   unsigned b : 2;
     48   unsigned c : 1;
     49 
     50   bool x;
     51 
     52   struct InnerBits {
     53     bool y;
     54 
     55     unsigned d : 16;
     56     unsigned e : 6;
     57     unsigned f : 2;
     58   } inner;
     59 };
     60 
     61 void testBitfields() {
     62   struct Bits bits;
     63 
     64   if (foo() && bits.b) // expected-warning {{garbage}}
     65     return;
     66   if (foo() && bits.inner.e) // expected-warning {{garbage}}
     67     return;
     68 
     69   bits.c = 1;
     70   clang_analyzer_eval(bits.c == 1); // expected-warning {{TRUE}}
     71 
     72   if (foo() && bits.b) // expected-warning {{garbage}}
     73     return;
     74   if (foo() && bits.x) // expected-warning {{garbage}}
     75     return;
     76 
     77   bits.x = true;
     78   clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}}
     79   bits.b = 2;
     80   clang_analyzer_eval(bits.x == true); // expected-warning{{TRUE}}
     81   if (foo() && bits.c) // no-warning
     82     return;
     83 
     84   bits.inner.e = 50;
     85   if (foo() && bits.inner.e) // no-warning
     86     return;
     87   if (foo() && bits.inner.y) // expected-warning {{garbage}}
     88     return;
     89   if (foo() && bits.inner.f) // expected-warning {{garbage}}
     90     return;
     91 
     92   extern struct InnerBits getInner();
     93   bits.inner = getInner();
     94 
     95   if (foo() && bits.inner.e) // no-warning
     96     return;
     97   if (foo() && bits.inner.y) // no-warning
     98     return;
     99   if (foo() && bits.inner.f) // no-warning
    100     return;
    101 
    102   bits.inner.f = 1;
    103 
    104   if (foo() && bits.inner.e) // no-warning
    105     return;
    106   if (foo() && bits.inner.y) // no-warning
    107     return;
    108   if (foo() && bits.inner.f) // no-warning
    109     return;
    110 
    111   if (foo() && bits.a) // expected-warning {{garbage}}
    112     return;
    113 }
    114 
    115 
    116 //-----------------------------------------------------------------------------
    117 // Incorrect behavior
    118 //-----------------------------------------------------------------------------
    119 
    120 void testTruncation() {
    121   struct Bits bits;
    122   bits.c = 0x11; // expected-warning{{implicit truncation}}
    123   // FIXME: We don't model truncation of bitfields.
    124   clang_analyzer_eval(bits.c == 1); // expected-warning {{FALSE}}
    125 }
    126