reference.cpp 3.3 KB

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