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