new.cpp revision e6f2bf86288bc45060b21c4f55a6153b8ba80443
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-store region -std=c++11 -verify %s
2#include "Inputs/system-header-simulator-cxx.h"
3
4void clang_analyzer_eval(bool);
5
6typedef __typeof__(sizeof(int)) size_t;
7extern "C" void *malloc(size_t);
8extern "C" void free(void *);
9
10int someGlobal;
11void testImplicitlyDeclaredGlobalNew() {
12  if (someGlobal != 0)
13    return;
14
15  // This used to crash because the global operator new is being implicitly
16  // declared and it does not have a valid source location. (PR13090)
17  void *x = ::operator new(0);
18  ::operator delete(x);
19
20  // Check that the new/delete did not invalidate someGlobal;
21  clang_analyzer_eval(someGlobal == 0); // expected-warning{{TRUE}}
22}
23
24void *testPlacementNew() {
25  int *x = (int *)malloc(sizeof(int));
26  *x = 1;
27  clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
28
29  void *y = new (x) int;
30  clang_analyzer_eval(x == y); // expected-warning{{TRUE}};
31  clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
32
33  return y;
34}
35
36void *operator new(size_t, size_t, int *);
37void *testCustomNew() {
38  int x[1] = {1};
39  clang_analyzer_eval(*x == 1); // expected-warning{{TRUE}};
40
41  void *y = new (0, x) int;
42  clang_analyzer_eval(*x == 1); // expected-warning{{UNKNOWN}};
43
44  return y; // no-warning
45}
46
47void *operator new(size_t, void *, void *);
48void *testCustomNewMalloc() {
49  int *x = (int *)malloc(sizeof(int));
50
51  // Should be no-warning (the custom allocator could have freed x).
52  void *y = new (0, x) int; // no-warning
53
54  return y;
55}
56
57void testScalarInitialization() {
58  int *n = new int(3);
59  clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
60
61  new (n) int();
62  clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
63
64  new (n) int{3};
65  clang_analyzer_eval(*n == 3); // expected-warning{{TRUE}}
66
67  new (n) int{};
68  clang_analyzer_eval(*n == 0); // expected-warning{{TRUE}}
69}
70
71struct PtrWrapper {
72  int *x;
73
74  PtrWrapper(int *input) : x(input) {}
75};
76
77PtrWrapper *testNewInvalidation() {
78  // Ensure that we don't consider this a leak.
79  return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
80}
81
82void testNewInvalidationPlacement(PtrWrapper *w) {
83  // Ensure that we don't consider this a leak.
84  new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
85}
86
87int **testNewInvalidationScalar() {
88  // Ensure that we don't consider this a leak.
89  return new (int *)(static_cast<int *>(malloc(4))); // no-warning
90}
91
92void testNewInvalidationScalarPlacement(int **p) {
93  // Ensure that we don't consider this a leak.
94  new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
95}
96
97void testCacheOut(PtrWrapper w) {
98  extern bool coin();
99  if (coin())
100    w.x = 0;
101  new (&w.x) (int*)(0); // we cache out here; don't crash
102}
103
104
105//--------------------------------------------------------------------
106// Check for intersection with other checkers from MallocChecker.cpp
107// bounded with unix.Malloc
108//--------------------------------------------------------------------
109
110// new/delete oparators are subjects of cplusplus.NewDelete.
111void testNewDeleteNoWarn() {
112  int i;
113  delete &i; // no-warning
114
115  int *p1 = new int;
116  delete ++p1; // no-warning
117
118  int *p2 = new int;
119  delete p2;
120  delete p2; // no-warning
121
122  int *p3 = new int; // no-warning
123}
124
125// unix.Malloc does not know about operators new/delete.
126void testDeleteMallocked() {
127  int *x = (int *)malloc(sizeof(int));
128  delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly.
129} // expected-warning{{Memory is never released; potential leak}}
130
131void testDeleteOpAfterFree() {
132  int *p = (int *)malloc(sizeof(int));
133  free(p);
134  operator delete(p); // expected-warning{{Use of memory after it is freed}}
135}
136
137void testDeleteAfterFree() {
138  int *p = (int *)malloc(sizeof(int));
139  free(p);
140  delete p; // expected-warning{{Use of memory after it is freed}}
141}
142
143void testStandardPlacementNewAfterFree() {
144  int *p = (int *)malloc(sizeof(int));
145  free(p);
146  p = new(p) int; // expected-warning{{Use of memory after it is freed}}
147}
148
149void testCustomPlacementNewAfterFree() {
150  int *p = (int *)malloc(sizeof(int));
151  free(p);
152  p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
153}
154
155//--------------------------------
156// Incorrectly-modelled behavior
157//--------------------------------
158
159int testNoInitialization() {
160  int *n = new int;
161
162  // Should warn that *n is uninitialized.
163  if (*n) { // no-warning
164    delete n;
165    return 0;
166  }
167  delete n;
168  return 1;
169}
170
171int testNoInitializationPlacement() {
172  int n;
173  new (&n) int;
174
175  // Should warn that n is uninitialized.
176  if (n) { // no-warning
177    return 0;
178  }
179  return 1;
180}
181