new.cpp revision b061720ddf88b4a1934dbbb1b874a424716cd7d7
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
97//--------------------------------------------------------------------
98// Check for intersection with other checkers from MallocChecker.cpp
99// bounded with unix.Malloc
100//--------------------------------------------------------------------
101
102// new/delete oparators are subjects of cplusplus.NewDelete.
103void testNewDeleteNoWarn() {
104  int i;
105  delete &i; // no-warning
106
107  int *p1 = new int;
108  delete ++p1; // no-warning
109
110  int *p2 = new int;
111  delete p2;
112  delete p2; // no-warning
113
114  int *p3 = new int; // no-warning
115}
116
117// unix.Malloc does not know about operators new/delete.
118void testDeleteMallocked() {
119  int *x = (int *)malloc(sizeof(int));
120  delete x; // FIXME: Shoud detect pointer escape and keep silent after 'delete' is modeled properly.
121} // expected-warning{{Memory is never released; potential leak}}
122
123void testDeleteOpAfterFree() {
124  int *p = (int *)malloc(sizeof(int));
125  free(p);
126  operator delete(p); // expected-warning{{Use of memory after it is freed}}
127}
128
129void testDeleteAfterFree() {
130  int *p = (int *)malloc(sizeof(int));
131  free(p);
132  delete p; // expected-warning{{Use of memory after it is freed}}
133}
134
135void testStandardPlacementNewAfterFree() {
136  int *p = (int *)malloc(sizeof(int));
137  free(p);
138  p = new(p) int; // expected-warning{{Use of memory after it is freed}}
139}
140
141void testCustomPlacementNewAfterFree() {
142  int *p = (int *)malloc(sizeof(int));
143  free(p);
144  p = new(0, p) int; // expected-warning{{Use of memory after it is freed}}
145}
146
147//--------------------------------
148// Incorrectly-modelled behavior
149//--------------------------------
150
151int testNoInitialization() {
152  int *n = new int;
153
154  // Should warn that *n is uninitialized.
155  if (*n) { // no-warning
156    delete n;
157    return 0;
158  }
159  delete n;
160  return 1;
161}
162
163int testNoInitializationPlacement() {
164  int n;
165  new (&n) int;
166
167  // Should warn that n is uninitialized.
168  if (n) { // no-warning
169    return 0;
170  }
171  return 1;
172}
173