array-struct-region.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  2. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  3. // RUN: -Wno-tautological-compare\
  4. // RUN: -x c %s
  5. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  6. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  7. // RUN: -Wno-tautological-compare\
  8. // RUN: -x c++ -std=c++14 %s
  9. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  10. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  11. // RUN: -Wno-tautological-compare\
  12. // RUN: -x c++ -std=c++17 %s
  13. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  14. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  15. // RUN: -Wno-tautological-compare\
  16. // RUN: -DINLINE -x c %s
  17. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  18. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  19. // RUN: -Wno-tautological-compare\
  20. // RUN: -DINLINE -x c++ -std=c++14 %s
  21. // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core\
  22. // RUN: -analyzer-checker=debug.ExprInspection -verify\
  23. // RUN: -Wno-tautological-compare\
  24. // RUN: -DINLINE -x c++ -std=c++17 %s
  25. void clang_analyzer_eval(int);
  26. struct S {
  27. int field;
  28. #if __cplusplus
  29. const struct S *getThis() const { return this; }
  30. const struct S *operator +() const { return this; }
  31. bool check() const { return this == this; }
  32. bool operator !() const { return this != this; }
  33. int operator *() const { return field; }
  34. #endif
  35. };
  36. #if __cplusplus
  37. const struct S *operator -(const struct S &s) { return &s; }
  38. bool operator ~(const struct S &s) { return (&s) != &s; }
  39. #endif
  40. #ifdef INLINE
  41. struct S getS() {
  42. struct S s = { 42 };
  43. return s;
  44. }
  45. #else
  46. struct S getS();
  47. #endif
  48. void testAssignment() {
  49. struct S s = getS();
  50. if (s.field != 42) return;
  51. clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
  52. s.field = 0;
  53. clang_analyzer_eval(s.field == 0); // expected-warning{{TRUE}}
  54. #if __cplusplus
  55. clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
  56. clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
  57. clang_analyzer_eval(-s == &s); // expected-warning{{TRUE}}
  58. clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
  59. clang_analyzer_eval(!s); // expected-warning{{FALSE}}
  60. clang_analyzer_eval(~s); // expected-warning{{FALSE}}
  61. clang_analyzer_eval(*s == 0); // expected-warning{{TRUE}}
  62. #endif
  63. }
  64. void testImmediateUse() {
  65. int x = getS().field;
  66. if (x != 42) return;
  67. clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
  68. #if __cplusplus
  69. clang_analyzer_eval((void *)getS().getThis() == (void *)&x); // expected-warning{{FALSE}}
  70. clang_analyzer_eval((void *)+getS() == (void *)&x); // expected-warning{{FALSE}}
  71. clang_analyzer_eval((void *)-getS() == (void *)&x); // expected-warning{{FALSE}}
  72. clang_analyzer_eval(getS().check()); // expected-warning{{TRUE}}
  73. clang_analyzer_eval(!getS()); // expected-warning{{FALSE}}
  74. clang_analyzer_eval(~getS()); // expected-warning{{FALSE}}
  75. #endif
  76. }
  77. int getConstrainedField(struct S s) {
  78. if (s.field != 42) return 42;
  79. return s.field;
  80. }
  81. int getAssignedField(struct S s) {
  82. s.field = 42;
  83. return s.field;
  84. }
  85. void testArgument() {
  86. clang_analyzer_eval(getConstrainedField(getS()) == 42); // expected-warning{{TRUE}}
  87. clang_analyzer_eval(getAssignedField(getS()) == 42); // expected-warning{{TRUE}}
  88. }
  89. void testImmediateUseParens() {
  90. int x = ((getS())).field;
  91. if (x != 42) return;
  92. clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
  93. clang_analyzer_eval(getConstrainedField(((getS()))) == 42); // expected-warning{{TRUE}}
  94. clang_analyzer_eval(getAssignedField(((getS()))) == 42); // expected-warning{{TRUE}}
  95. #if __cplusplus
  96. clang_analyzer_eval(((getS())).check()); // expected-warning{{TRUE}}
  97. clang_analyzer_eval(!((getS()))); // expected-warning{{FALSE}}
  98. clang_analyzer_eval(~((getS()))); // expected-warning{{FALSE}}
  99. #endif
  100. }
  101. //--------------------
  102. // C++-only tests
  103. //--------------------
  104. #if __cplusplus
  105. void testReferenceAssignment() {
  106. const S &s = getS();
  107. if (s.field != 42) return;
  108. clang_analyzer_eval(s.field == 42); // expected-warning{{TRUE}}
  109. clang_analyzer_eval(s.getThis() == &s); // expected-warning{{TRUE}}
  110. clang_analyzer_eval(+s == &s); // expected-warning{{TRUE}}
  111. clang_analyzer_eval(s.check()); // expected-warning{{TRUE}}
  112. clang_analyzer_eval(!s); // expected-warning{{FALSE}}
  113. clang_analyzer_eval(~s); // expected-warning{{FALSE}}
  114. clang_analyzer_eval(*s == 42); // expected-warning{{TRUE}}
  115. }
  116. int getConstrainedFieldRef(const S &s) {
  117. if (s.field != 42) return 42;
  118. return s.field;
  119. }
  120. bool checkThis(const S &s) {
  121. return s.getThis() == &s;
  122. }
  123. bool checkThisOp(const S &s) {
  124. return +s == &s;
  125. }
  126. bool checkThisStaticOp(const S &s) {
  127. return -s == &s;
  128. }
  129. void testReferenceArgument() {
  130. clang_analyzer_eval(getConstrainedFieldRef(getS()) == 42); // expected-warning{{TRUE}}
  131. clang_analyzer_eval(checkThis(getS())); // expected-warning{{TRUE}}
  132. clang_analyzer_eval(checkThisOp(getS())); // expected-warning{{TRUE}}
  133. clang_analyzer_eval(checkThisStaticOp(getS())); // expected-warning{{TRUE}}
  134. }
  135. int getConstrainedFieldOp(S s) {
  136. if (*s != 42) return 42;
  137. return *s;
  138. }
  139. int getConstrainedFieldRefOp(const S &s) {
  140. if (*s != 42) return 42;
  141. return *s;
  142. }
  143. void testImmediateUseOp() {
  144. int x = *getS();
  145. if (x != 42) return;
  146. clang_analyzer_eval(x == 42); // expected-warning{{TRUE}}
  147. clang_analyzer_eval(getConstrainedFieldOp(getS()) == 42); // expected-warning{{TRUE}}
  148. clang_analyzer_eval(getConstrainedFieldRefOp(getS()) == 42); // expected-warning{{TRUE}}
  149. }
  150. namespace EmptyClass {
  151. struct Base {
  152. int& x;
  153. Base(int& x) : x(x) {}
  154. };
  155. struct Derived : public Base {
  156. Derived(int& x) : Base(x) {}
  157. void operator=(int a) { x = a; }
  158. };
  159. Derived ref(int& a) { return Derived(a); }
  160. // There used to be a warning here, because analyzer treated Derived as empty.
  161. int test() {
  162. int a;
  163. ref(a) = 42;
  164. return a; // no warning
  165. }
  166. }
  167. #if __cplusplus >= 201703L
  168. namespace aggregate_inheritance_cxx17 {
  169. struct A {
  170. int x;
  171. };
  172. struct B {
  173. int y;
  174. };
  175. struct C: B {
  176. int z;
  177. };
  178. struct D: A, C {
  179. int w;
  180. };
  181. void foo() {
  182. D d{1, 2, 3, 4};
  183. clang_analyzer_eval(d.x == 1); // expected-warning{{TRUE}}
  184. clang_analyzer_eval(d.y == 2); // expected-warning{{TRUE}}
  185. clang_analyzer_eval(d.z == 3); // expected-warning{{TRUE}}
  186. clang_analyzer_eval(d.w == 4); // expected-warning{{TRUE}}
  187. }
  188. } // namespace aggregate_inheritance_cxx17
  189. #endif
  190. namespace flex_array_inheritance_cxx17 {
  191. struct A {
  192. int flexible_array[];
  193. };
  194. struct B {
  195. long cookie;
  196. };
  197. struct C : B {
  198. A a;
  199. };
  200. void foo() {
  201. C c{}; // no-crash
  202. }
  203. } // namespace flex_array_inheritance_cxx17
  204. #endif