Home | History | Annotate | Download | only in Analysis
      1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
      2 
      3 void clang_analyzer_eval(bool);
      4 
      5 void usePointer(int * const *);
      6 void useReference(int * const &);
      7 
      8 void testPointer() {
      9   int x;
     10   int *p;
     11 
     12   p = &x;
     13   x = 42;
     14   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     15   usePointer(&p);
     16   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     17 
     18   p = &x;
     19   x = 42;
     20   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     21   useReference(p);
     22   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     23 
     24   int * const cp1 = &x;
     25   x = 42;
     26   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     27   usePointer(&cp1);
     28   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     29 
     30   int * const cp2 = &x;
     31   x = 42;
     32   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     33   useReference(cp2);
     34   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     35 }
     36 
     37 
     38 struct Wrapper {
     39   int *ptr;
     40 };
     41 
     42 void useStruct(Wrapper &w);
     43 void useConstStruct(const Wrapper &w);
     44 
     45 void testPointerStruct() {
     46   int x;
     47   Wrapper w;
     48 
     49   w.ptr = &x;
     50   x = 42;
     51   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     52   useStruct(w);
     53   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     54 
     55   w.ptr = &x;
     56   x = 42;
     57   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     58   useConstStruct(w);
     59   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     60 }
     61 
     62 
     63 struct RefWrapper {
     64   int &ref;
     65 };
     66 
     67 void useStruct(RefWrapper &w);
     68 void useConstStruct(const RefWrapper &w);
     69 
     70 void testReferenceStruct() {
     71   int x;
     72   RefWrapper w = { x };
     73 
     74   x = 42;
     75   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     76   useStruct(w);
     77   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     78 }
     79 
     80 // FIXME: This test is split into two functions because region invalidation
     81 // does not preserve reference bindings. <rdar://problem/13320347>
     82 void testConstReferenceStruct() {
     83   int x;
     84   RefWrapper w = { x };
     85 
     86   x = 42;
     87   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
     88   useConstStruct(w);
     89   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
     90 }
     91 
     92 
     93 void usePointerPure(int * const *) __attribute__((pure));
     94 void usePointerConst(int * const *) __attribute__((const));
     95 
     96 void testPureConst() {
     97   extern int global;
     98   int x;
     99   int *p;
    100 
    101   p = &x;
    102   x = 42;
    103   global = -5;
    104   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
    105   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
    106 
    107   usePointerPure(&p);
    108   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
    109   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
    110 
    111   usePointerConst(&p);
    112   clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
    113   clang_analyzer_eval(global == -5); // expected-warning{{TRUE}}
    114 
    115   usePointer(&p);
    116   clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}}
    117   clang_analyzer_eval(global == -5); // expected-warning{{UNKNOWN}}
    118 }
    119 
    120 
    121 struct PlainStruct {
    122   int x, y;
    123   mutable int z;
    124 };
    125 
    126 PlainStruct glob;
    127 
    128 void useAnything(void *);
    129 void useAnythingConst(const void *);
    130 
    131 void testInvalidationThroughBaseRegionPointer() {
    132   PlainStruct s1;
    133   s1.x = 1;
    134   s1.z = 1;
    135   clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
    136   clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
    137   // Not only passing a structure pointer through const pointer parameter,
    138   // but also passing a field pointer through const pointer parameter
    139   // should preserve the contents of the structure.
    140   useAnythingConst(&(s1.y));
    141   clang_analyzer_eval(s1.x == 1); // expected-warning{{TRUE}}
    142   // FIXME: Should say "UNKNOWN", because it is not uncommon to
    143   // modify a mutable member variable through const pointer.
    144   clang_analyzer_eval(s1.z == 1); // expected-warning{{TRUE}}
    145   useAnything(&(s1.y));
    146   clang_analyzer_eval(s1.x == 1); // expected-warning{{UNKNOWN}}
    147 }
    148 
    149 
    150 void useFirstConstSecondNonConst(const void *x, void *y);
    151 void useFirstNonConstSecondConst(void *x, const void *y);
    152 
    153 void testMixedConstNonConstCalls() {
    154   PlainStruct s2;
    155   s2.x = 1;
    156   useFirstConstSecondNonConst(&(s2.x), &(s2.y));
    157   clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
    158   s2.x = 1;
    159   useFirstNonConstSecondConst(&(s2.x), &(s2.y));
    160   clang_analyzer_eval(s2.x == 1); // expected-warning{{UNKNOWN}}
    161   s2.y = 1;
    162   useFirstConstSecondNonConst(&(s2.x), &(s2.y));
    163   clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
    164   s2.y = 1;
    165   useFirstNonConstSecondConst(&(s2.x), &(s2.y));
    166   clang_analyzer_eval(s2.y == 1); // expected-warning{{UNKNOWN}}
    167 }
    168