1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify -Wno-null-dereference %s 2 // RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s 3 4 void clang_analyzer_eval(bool); 5 6 typedef typeof(sizeof(int)) size_t; 7 void malloc (size_t); 8 9 void f1() { 10 int const &i = 3; 11 int b = i; 12 13 int *p = 0; 14 15 if (b != 3) 16 *p = 1; // no-warning 17 } 18 19 char* ptr(); 20 char& ref(); 21 22 // These next two tests just shouldn't crash. 23 char t1 () { 24 ref() = 'c'; 25 return '0'; 26 } 27 28 // just a sanity test, the same behavior as t1() 29 char t2 () { 30 *ptr() = 'c'; 31 return '0'; 32 } 33 34 // Each of the tests below is repeated with pointers as well as references. 35 // This is mostly a sanity check, but then again, both should work! 36 char t3 () { 37 char& r = ref(); 38 r = 'c'; // no-warning 39 if (r) return r; 40 return *(char*)0; // no-warning 41 } 42 43 char t4 () { 44 char* p = ptr(); 45 *p = 'c'; // no-warning 46 if (*p) return *p; 47 return *(char*)0; // no-warning 48 } 49 50 char t5 (char& r) { 51 r = 'c'; // no-warning 52 if (r) return r; 53 return *(char*)0; // no-warning 54 } 55 56 char t6 (char* p) { 57 *p = 'c'; // no-warning 58 if (*p) return *p; 59 return *(char*)0; // no-warning 60 } 61 62 63 // PR13440 / <rdar://problem/11977113> 64 // Test that the array-to-pointer decay works for array references as well. 65 // More generally, when we want an lvalue for a reference field, we still need 66 // to do one level of load. 67 namespace PR13440 { 68 typedef int T[1]; 69 struct S { 70 T &x; 71 72 int *m() { return x; } 73 }; 74 75 struct S2 { 76 int (&x)[1]; 77 78 int *m() { return x; } 79 }; 80 81 void test() { 82 int a[1]; 83 S s = { a }; 84 S2 s2 = { a }; 85 86 if (s.x != a) return; 87 if (s2.x != a) return; 88 89 a[0] = 42; 90 clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}} 91 clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}} 92 } 93 } 94 95 void testNullReference() { 96 int *x = 0; 97 int &y = *x; // expected-warning{{Dereference of null pointer}} 98 y = 5; 99 } 100 101 void testRetroactiveNullReference(int *x) { 102 // According to the C++ standard, there is no such thing as a 103 // "null reference". So the 'if' statement ought to be dead code. 104 // However, Clang (and other compilers) don't actually check that a pointer 105 // value is non-null in the implementation of references, so it is possible 106 // to produce a supposed "null reference" at runtime. The analyzer shoeuld 107 // still warn when it can prove such errors. 108 int &y = *x; 109 if (x != 0) 110 return; 111 y = 5; // expected-warning{{Dereference of null pointer}} 112 } 113 114 void testReferenceAddress(int &x) { 115 clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}} 116 clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}} 117 118 struct S { int &x; }; 119 120 extern S *getS(); 121 clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}} 122 } 123 124 125 // ------------------------------------ 126 // False negatives 127 // ------------------------------------ 128 129 namespace rdar11212286 { 130 class B{}; 131 132 B test() { 133 B *x = 0; 134 return *x; // should warn here! 135 } 136 137 B &testRef() { 138 B *x = 0; 139 return *x; // should warn here! 140 } 141 } 142 143 void testReferenceFieldAddress() { 144 struct S { int &x; }; 145 146 extern S getS(); 147 clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}} 148 } 149