243 lines · cpp
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core,debug.ExprInspection -verify -Wno-null-dereference -Wno-tautological-undefined-compare -analyzer-config eagerly-assume=false %s2 3void clang_analyzer_eval(bool);4 5typedef typeof(sizeof(int)) size_t;6void malloc (size_t);7 8void f1() {9 int const &i = 3;10 int b = i;11 12 int *p = 0;13 14 if (b != 3)15 *p = 1; // no-warning16}17 18char* ptr();19char& ref();20 21// These next two tests just shouldn't crash.22char t1 () {23 ref() = 'c';24 return '0';25}26 27// just a basic correctness test, the same behavior as t1()28char t2 () {29 *ptr() = 'c';30 return '0';31}32 33// Each of the tests below is repeated with pointers as well as references.34// This is mostly a basic correctness check, but then again, both should work!35char t3 () {36 char& r = ref();37 r = 'c'; // no-warning38 if (r) return r;39 return *(char*)0; // no-warning40}41 42char t4 () {43 char* p = ptr();44 *p = 'c'; // no-warning45 if (*p) return *p;46 return *(char*)0; // no-warning47}48 49char t5 (char& r) {50 r = 'c'; // no-warning51 if (r) return r;52 return *(char*)0; // no-warning53}54 55char t6 (char* p) {56 *p = 'c'; // no-warning57 if (*p) return *p;58 return *(char*)0; // no-warning59}60 61 62// PR1344063// Test that the array-to-pointer decay works for array references as well.64// More generally, when we want an lvalue for a reference field, we still need65// to do one level of load.66namespace PR13440 {67 typedef int T[1];68 struct S {69 T &x;70 71 int *m() { return x; }72 };73 74 struct S2 {75 int (&x)[1];76 77 int *m() { return x; }78 79 void testArrayToPointerDecayWithNonTypedValueRegion() {80 int *p = x;81 int *q = x;82 clang_analyzer_eval(p[0] == q[0]); // expected-warning{{TRUE}}83 }84 85 };86 87 void test() {88 int a[1];89 S s = { a };90 S2 s2 = { a };91 92 if (s.x != a) return; // expected-warning {{comparison between two arrays}}93 if (s2.x != a) return; // expected-warning {{comparison between two arrays}}94 95 a[0] = 42;96 clang_analyzer_eval(s.x[0] == 42); // expected-warning{{TRUE}}97 clang_analyzer_eval(s2.x[0] == 42); // expected-warning{{TRUE}}98 }99}100 101void testNullReference() {102 int *x = 0;103 int &y = *x; // expected-warning{{Dereference of null pointer}}104 y = 5;105}106 107void testRetroactiveNullReference(int *x) {108 // According to the C++ standard, there is no such thing as a109 // "null reference". So the 'if' statement ought to be dead code.110 // However, Clang (and other compilers) don't actually check that a pointer111 // value is non-null in the implementation of references, so it is possible112 // to produce a supposed "null reference" at runtime. The analyzer should113 // still warn when it can prove such errors.114 int &y = *x;115 if (x != 0)116 return;117 y = 5; // expected-warning{{Dereference of null pointer}}118}119 120namespace TestReferenceAddress {121struct S { int &x; };122S getS();123S *getSP();124 125void testReferenceAddress(int &x) {126 clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}127 clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}128 clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}129 clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}130}131}132 133void testFunctionPointerReturn(void *opaque) {134 typedef int &(*RefFn)();135 136 RefFn getRef = (RefFn)opaque;137 138 // Don't crash writing to or reading from this reference.139 int &x = getRef();140 x = 42;141 clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}142}143 144int &testReturnNullReference() {145 int *x = 0;146 return *x; // expected-warning{{Returning null reference}}147}148 149char &refFromPointer() {150 return *ptr();151}152 153void testReturnReference() {154 clang_analyzer_eval(ptr() == 0); // expected-warning{{UNKNOWN}}155 clang_analyzer_eval(&refFromPointer() == 0); // expected-warning{{FALSE}}156}157 158void intRefParam(int &r) {159 ;160}161 162void test(int *ptr) {163 clang_analyzer_eval(ptr == 0); // expected-warning{{UNKNOWN}}164 165 extern void use(int &ref);166 use(*ptr);167 168 clang_analyzer_eval(ptr == 0); // expected-warning{{FALSE}}169}170 171void testIntRefParam() {172 int i = 0;173 intRefParam(i); // no-warning174}175 176int refParam(int &byteIndex) {177 return byteIndex;178}179 180void testRefParam(int *p) {181 if (p)182 ;183 refParam(*p); // expected-warning {{Forming reference to null pointer}}184}185 186int ptrRefParam(int *&byteIndex) {187 return *byteIndex; // expected-warning {{Dereference of null pointer}}188}189void testRefParam2() {190 int *p = 0;191 int *&rp = p;192 ptrRefParam(rp);193}194 195int *maybeNull() {196 extern bool coin();197 static int x;198 return coin() ? &x : 0;199}200 201void use(int &x) {202 x = 1; // no-warning203}204 205void testSuppression() {206 use(*maybeNull());207}208 209namespace rdar11212286 {210 class B{};211 212 B test() {213 B *x = 0;214 return *x; // expected-warning {{Forming reference to null pointer}}215 }216 217 B testif(B *x) {218 if (x)219 ;220 return *x; // expected-warning {{Forming reference to null pointer}}221 }222 223 void idc(B *x) {224 if (x)225 ;226 }227 228 B testidc(B *x) {229 idc(x);230 return *x; // no-warning231 }232}233 234namespace PR15694 {235 class C {236 bool bit : 1;237 template <class T> void bar(const T &obj) {}238 void foo() {239 bar(bit); // don't crash240 }241 };242}243