/clang/test/Analysis/diagnostics/no-store-func-path-notes.cpp

https://gitlab.com/williamwp/riscv-rv32x-llvm · C++ · 376 lines · 237 code · 67 blank · 72 comment · 13 complexity · 02bdf5b698200328e9bf884efe9972c5 MD5 · raw file

  1. // RUN: %clang_analyze_cc1 -x c++ -std=c++14 -analyzer-checker=core -analyzer-output=text -verify %s
  2. int initializer1(int &p, int x) {
  3. if (x) { // expected-note{{'x' is 0}}
  4. // expected-note@-1{{Taking false branch}}
  5. p = 1;
  6. return 0;
  7. } else {
  8. return 1; // expected-note {{Returning without writing to 'p'}}
  9. }
  10. }
  11. int param_not_initialized_by_func() {
  12. int outP; // expected-note {{'outP' declared without an initial value}}
  13. int out = initializer1(outP, 0); // expected-note{{Calling 'initializer1'}}
  14. // expected-note@-1{{Returning from 'initializer1'}}
  15. return outP; // expected-note{{Undefined or garbage value returned to caller}}
  16. // expected-warning@-1{{Undefined or garbage value returned to caller}}
  17. }
  18. struct S {
  19. int initialize(int *p, int param) {
  20. if (param) { // expected-note{{'param' is 0}}
  21. // expected-note@-1{{Taking false branch}}
  22. *p = 1;
  23. return 1;
  24. }
  25. return 0; // expected-note{{Returning without writing to '*p'}}
  26. }
  27. };
  28. int use(S *s) {
  29. int p; //expected-note{{'p' declared without an initial value}}
  30. s->initialize(&p, 0); //expected-note{{Calling 'S::initialize'}}
  31. //expected-note@-1{{Returning from 'S::initialize'}}
  32. return p; // expected-warning{{Undefined or garbage value returned to caller}}
  33. // expected-note@-1{{Undefined or garbage value returned to caller}}
  34. }
  35. int initializer2(const int &p) {
  36. return 0;
  37. }
  38. int no_msg_const_ref() {
  39. int p; //expected-note{{'p' declared without an initial value}}
  40. initializer2(p);
  41. return p; // expected-warning{{Undefined or garbage value returned to caller}}
  42. // expected-note@-1{{Undefined or garbage value returned to caller}}
  43. }
  44. void nested() {}
  45. void init_in_nested_func(int **x) {
  46. *x = 0; // expected-note{{Null pointer value stored to 'y'}}
  47. nested();
  48. } // no-note
  49. int call_init_nested() {
  50. int x = 0;
  51. int *y = &x;
  52. init_in_nested_func(&y); // expected-note{{Calling 'init_in_nested_func'}}
  53. // expected-note@-1{{Returning from 'init_in_nested_func'}}
  54. return *y; //expected-warning{{Dereference of null pointer (loaded from variable 'y')}}
  55. //expected-note@-1{{Dereference of null pointer (loaded from variable 'y')}}
  56. }
  57. struct A {
  58. int x;
  59. int y;
  60. };
  61. void partial_init_by_reference(A &a) {
  62. a.x = 0;
  63. } // expected-note {{Returning without writing to 'a.y'}}
  64. int use_partial_init_by_reference() {
  65. A a;
  66. partial_init_by_reference(a); // expected-note{{Calling 'partial_init_by_reference'}}
  67. // expected-note@-1{{Returning from 'partial_init_by_reference'}}
  68. return a.y; // expected-warning{{Undefined or garbage value returned to caller}}
  69. // expected-note@-1{{Undefined or garbage value returned to caller}}
  70. }
  71. struct B : A {
  72. };
  73. void partially_init_inherited_struct(B *b) {
  74. b->x = 0;
  75. } // expected-note{{Returning without writing to 'b->y'}}
  76. int use_partially_init_inherited_struct() {
  77. B b;
  78. partially_init_inherited_struct(&b); // expected-note{{Calling 'partially_init_inherited_struct'}}
  79. // expected-note@-1{{Returning from 'partially_init_inherited_struct'}}
  80. return b.y; // expected-warning{{Undefined or garbage value returned to caller}}
  81. // expected-note@-1{{Undefined or garbage value returned to caller}}
  82. }
  83. struct C {
  84. int x;
  85. int y;
  86. C(int pX, int pY) : x(pX) {} // expected-note{{Returning without writing to 'this->y'}}
  87. C(int pX, int pY, bool Flag) {
  88. x = pX;
  89. if (Flag) // expected-note{{Assuming 'Flag' is true}}
  90. // expected-note@-1{{Taking true branch}}
  91. return; // expected-note{{Returning without writing to 'this->y'}}
  92. y = pY;
  93. }
  94. };
  95. int use_constructor() {
  96. C c(0, 0); // expected-note{{Calling constructor for 'C'}}
  97. // expected-note@-1{{Returning from constructor for 'C'}}
  98. return c.y; // expected-note{{Undefined or garbage value returned to caller}}
  99. // expected-warning@-1{{Undefined or garbage value returned to caller}}
  100. }
  101. int coin();
  102. int use_other_constructor() {
  103. C c(0, 0, coin()); // expected-note{{Calling constructor for 'C'}}
  104. // expected-note@-1{{Returning from constructor for 'C'}}
  105. return c.y; // expected-note{{Undefined or garbage value returned to caller}}
  106. // expected-warning@-1{{Undefined or garbage value returned to caller}}
  107. }
  108. struct D {
  109. void initialize(int *);
  110. };
  111. void D::initialize(int *p) {
  112. } // expected-note{{Returning without writing to '*p'}}
  113. int use_d_initializer(D* d) {
  114. int p; // expected-note {{'p' declared without an initial value}}
  115. d->initialize(&p); // expected-note{{Calling 'D::initialize'}}
  116. // expected-note@-1{{Returning from 'D::initialize'}}
  117. return p; // expected-note{{Undefined or garbage value returned to caller}}
  118. // expected-warning@-1{{Undefined or garbage value returned to caller}}
  119. }
  120. struct S2 {
  121. int x;
  122. };
  123. int pointerreference(S2* &s) {
  124. if (coin()) // expected-note{{Assuming the condition is true}}
  125. // expected-note@-1{{Taking true branch}}
  126. return 1; // expected-note{{Returning without writing to 's->x'}}
  127. s->x = 0;
  128. return 0;
  129. }
  130. int usepointerreference() {
  131. S2 s;
  132. S2* p = &s;
  133. pointerreference(p); //expected-note{{Calling 'pointerreference'}}
  134. //expected-note@-1{{Returning from 'pointerreference'}}
  135. return s.x; // expected-warning{{Undefined or garbage value returned to caller}}
  136. // expected-note@-1{{Undefined or garbage value returned to caller}}
  137. }
  138. void *has_no_argument_and_returns_null(void) {
  139. return 0;
  140. }
  141. void rdar40335545() {
  142. int local; // expected-note{{}}
  143. void (*takes_int_ptr_argument)(int *) = (void (*)(int*))has_no_argument_and_returns_null;
  144. takes_int_ptr_argument(&local); // no-crash
  145. int useLocal = local; //expected-warning{{}}
  146. //expected-note@-1{{}}
  147. (void)useLocal;
  148. }
  149. ////////
  150. struct HasRef {
  151. int &a;
  152. HasRef(int &a) : a(a) {}
  153. };
  154. void maybeInitialize(const HasRef &&pA) {
  155. if (coin()) // expected-note{{Assuming the condition is false}}
  156. // expected-note@-1{{Taking false branch}}
  157. pA.a = 120;
  158. } // expected-note{{Returning without writing to 'pA.a'}}
  159. int useMaybeInitializerWritingIntoField() {
  160. int z; // expected-note{{'z' declared without an initial value}}
  161. maybeInitialize(HasRef(z)); // expected-note{{Calling constructor for 'HasRef'}}
  162. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  163. // expected-note@-2{{Calling 'maybeInitialize'}}
  164. // expected-note@-3{{Returning from 'maybeInitialize'}}
  165. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  166. // expected-note@-1{{Undefined or garbage value returned to caller}}
  167. }
  168. ////////
  169. struct HasRefToItself {
  170. HasRefToItself &Ref; // no infinite loop
  171. int &z;
  172. HasRefToItself(int &z) : Ref(*this), z(z) {}
  173. };
  174. void maybeInitialize(const HasRefToItself &&pA) {
  175. if (coin()) // expected-note{{Assuming the condition is false}}
  176. // expected-note@-1{{Taking false branch}}
  177. pA.z = 120;
  178. } // expected-note{{Returning without writing to 'pA.Ref.z'}}
  179. int useMaybeInitializerWritingIntoFieldWithRefToItself() {
  180. int z; // expected-note{{'z' declared without an initial value}}
  181. maybeInitialize(HasRefToItself(z)); // expected-note{{Calling constructor for 'HasRefToItself'}}
  182. // expected-note@-1{{Returning from constructor for 'HasRefToItself'}}
  183. // expected-note@-2{{Calling 'maybeInitialize'}}
  184. // expected-note@-3{{Returning from 'maybeInitialize'}}
  185. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  186. // expected-note@-1{{Undefined or garbage value returned to caller}}
  187. }
  188. ////
  189. void maybeInitialize(const HasRef *pA) {
  190. if (coin()) // expected-note{{Assuming the condition is false}}
  191. // expected-note@-1{{Taking false branch}}
  192. pA->a = 120;
  193. } // expected-note{{Returning without writing to 'pA->a'}}
  194. int useMaybeInitializerStructByPointer() {
  195. int z; // expected-note{{'z' declared without an initial value}}
  196. HasRef wrapper(z); // expected-note{{Calling constructor for 'HasRef'}}
  197. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  198. maybeInitialize(&wrapper); // expected-note{{Calling 'maybeInitialize'}}
  199. // expected-note@-1{{Returning from 'maybeInitialize'}}
  200. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  201. // expected-note@-1{{Undefined or garbage value returned to caller}}
  202. }
  203. ////////
  204. struct HasParentWithRef : public HasRef {
  205. HasParentWithRef(int &a) : HasRef(a) {} // expected-note{{Calling constructor for 'HasRef'}}
  206. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  207. };
  208. void maybeInitializeWithParent(const HasParentWithRef &pA) {
  209. if (coin()) // expected-note{{Assuming the condition is false}}
  210. // expected-note@-1{{Taking false branch}}
  211. pA.a = 120;
  212. } // expected-note{{Returning without writing to 'pA.a'}}
  213. int useMaybeInitializerWritingIntoParentField() {
  214. int z; // expected-note{{'z' declared without an initial value}}
  215. maybeInitializeWithParent(HasParentWithRef(z)); // expected-note{{Calling constructor for 'HasParentWithRef'}}
  216. // expected-note@-1{{Returning from constructor for 'HasParentWithRef'}}
  217. // expected-note@-2{{Calling 'maybeInitializeWithParent'}}
  218. // expected-note@-3{{Returning from 'maybeInitializeWithParent'}}
  219. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  220. // expected-note@-1{{Undefined or garbage value returned to caller}}
  221. }
  222. ////////
  223. struct HasIndirectRef {
  224. HasRef &Ref;
  225. HasIndirectRef(HasRef &Ref) : Ref(Ref) {}
  226. };
  227. void maybeInitializeIndirectly(const HasIndirectRef &pA) {
  228. if (coin()) // expected-note{{Assuming the condition is false}}
  229. // expected-note@-1{{Taking false branch}}
  230. pA.Ref.a = 120;
  231. } // expected-note{{Returning without writing to 'pA.Ref.a'}}
  232. int useMaybeInitializeIndirectly() {
  233. int z; // expected-note{{'z' declared without an initial value}}
  234. HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
  235. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  236. maybeInitializeIndirectly(HasIndirectRef(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
  237. // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
  238. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  239. // expected-note@-1{{Undefined or garbage value returned to caller}}
  240. }
  241. ////////
  242. struct HasIndirectRefByValue {
  243. HasRef Ref;
  244. HasIndirectRefByValue(HasRef Ref) : Ref(Ref) {}
  245. };
  246. void maybeInitializeIndirectly(const HasIndirectRefByValue &pA) {
  247. if (coin()) // expected-note{{Assuming the condition is false}}
  248. // expected-note@-1{{Taking false branch}}
  249. pA.Ref.a = 120;
  250. } // expected-note{{Returning without writing to 'pA.Ref.a'}}
  251. int useMaybeInitializeIndirectlyIndirectRefByValue() {
  252. int z; // expected-note{{'z' declared without an initial value}}
  253. HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
  254. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  255. maybeInitializeIndirectly(HasIndirectRefByValue(r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
  256. // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
  257. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  258. // expected-note@-1{{Undefined or garbage value returned to caller}}
  259. }
  260. ////////
  261. struct HasIndirectPointerRef {
  262. HasRef *Ref;
  263. HasIndirectPointerRef(HasRef *Ref) : Ref(Ref) {}
  264. };
  265. void maybeInitializeIndirectly(const HasIndirectPointerRef &pA) {
  266. if (coin()) // expected-note{{Assuming the condition is false}}
  267. // expected-note@-1{{Taking false branch}}
  268. pA.Ref->a = 120;
  269. } // expected-note{{Returning without writing to 'pA.Ref->a'}}
  270. int useMaybeInitializeIndirectlyWithPointer() {
  271. int z; // expected-note{{'z' declared without an initial value}}
  272. HasRef r(z); // expected-note{{Calling constructor for 'HasRef'}}
  273. // expected-note@-1{{Returning from constructor for 'HasRef'}}
  274. maybeInitializeIndirectly(HasIndirectPointerRef(&r)); // expected-note{{Calling 'maybeInitializeIndirectly'}}
  275. // expected-note@-1{{Returning from 'maybeInitializeIndirectly'}}
  276. return z; // expected-warning{{Undefined or garbage value returned to caller}}
  277. // expected-note@-1{{Undefined or garbage value returned to caller}}
  278. }
  279. ////////
  280. struct HasFieldA {
  281. int x;
  282. };
  283. struct HasFieldB {
  284. int x;
  285. };
  286. void maybeInitializeHasField(HasFieldA *b) {
  287. if (coin()) // expected-note{{Assuming the condition is false}}
  288. // expected-note@-1{{Taking false branch}}
  289. ((HasFieldB*)b)->x = 120;
  290. }
  291. int forceElementRegionApperence() {
  292. HasFieldA a;
  293. maybeInitializeHasField(&a); // expected-note{{Calling 'maybeInitializeHasField'}}
  294. // expected-note@-1{{Returning from 'maybeInitializeHasField'}}
  295. return ((HasFieldB*)&a)->x; // expected-warning{{Undefined or garbage value returned to caller}}
  296. // expected-note@-1{{Undefined or garbage value returned to caller}}
  297. }
  298. ////////
  299. struct HasForgottenField {
  300. int x;
  301. HasForgottenField() {} // expected-note{{Returning without writing to 'this->x'}}
  302. };
  303. // Test that tracking across exclamation mark works.
  304. bool tracksThroughExclamationMark() {
  305. HasForgottenField a; // expected-note{{Calling default constructor for 'HasForgottenField'}}
  306. // expected-note@-1{{Returning from default constructor for 'HasForgottenField'}}
  307. return !a.x; // expected-warning{{Undefined or garbage value returned to caller}}
  308. // expected-note@-1{{Undefined or garbage value returned to caller}}
  309. }