1 | // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-allocator-inlining=true -std=c++11 -verify -analyzer-config eagerly-assume=false %s |
2 | |
3 | void clang_analyzer_eval(bool); |
4 | void clang_analyzer_dump(int); |
5 | |
6 | typedef __typeof__(sizeof(int)) size_t; |
7 | |
8 | void *conjure(); |
9 | void exit(int); |
10 | |
11 | struct S; |
12 | |
13 | S *global_s; |
14 | |
15 | // Recursive operator kinda placement new. |
16 | void *operator new(size_t size, S *place); |
17 | |
18 | enum class ConstructionKind : char { |
19 | Garbage, |
20 | Recursive |
21 | }; |
22 | |
23 | struct S { |
24 | public: |
25 | int x; |
26 | S(): x(1) {} |
27 | S(int y): x(y) {} |
28 | |
29 | S(ConstructionKind k) { |
30 | switch (k) { |
31 | case ConstructionKind::Recursive: { // Call one more operator new 'r'ecursively. |
32 | S *s = new (nullptr) S(5); |
33 | x = s->x + 1; |
34 | global_s = s; |
35 | return; |
36 | } |
37 | case ConstructionKind::Garbage: { |
38 | // Leaves garbage in 'x'. |
39 | } |
40 | } |
41 | } |
42 | ~S() {} |
43 | }; |
44 | |
45 | // Do not try this at home! |
46 | void *operator new(size_t size, S *place) { |
47 | if (!place) |
48 | return new S(); |
49 | return place; |
50 | } |
51 | |
52 | void testThatCharConstructorIndeedYieldsGarbage() { |
53 | S *s = new S(ConstructionKind::Garbage); |
54 | clang_analyzer_eval(s->x == 0); // expected-warning{{UNKNOWN}} |
55 | clang_analyzer_eval(s->x == 1); // expected-warning{{UNKNOWN}} |
56 | // FIXME: This should warn, but MallocChecker doesn't default-bind regions |
57 | // returned by standard operator new to garbage. |
58 | s->x += 1; // no-warning |
59 | delete s; |
60 | } |
61 | |
62 | |
63 | void testChainedOperatorNew() { |
64 | S *s; |
65 | // * Evaluate standard new. |
66 | // * Evaluate constructor S(3). |
67 | // * Bind value for standard new. |
68 | // * Evaluate our custom new. |
69 | // * Evaluate constructor S(Garbage). |
70 | // * Bind value for our custom new. |
71 | s = new (new S(3)) S(ConstructionKind::Garbage); |
72 | clang_analyzer_eval(s->x == 3); // expected-warning{{TRUE}} |
73 | // expected-warning@+9{{Potential leak of memory pointed to by 's'}} |
74 | |
75 | // * Evaluate standard new. |
76 | // * Evaluate constructor S(Garbage). |
77 | // * Bind value for standard new. |
78 | // * Evaluate our custom new. |
79 | // * Evaluate constructor S(4). |
80 | // * Bind value for our custom new. |
81 | s = new (new S(ConstructionKind::Garbage)) S(4); |
82 | clang_analyzer_eval(s->x == 4); // expected-warning{{TRUE}} |
83 | delete s; |
84 | |
85 | // -> Enter our custom new (nullptr). |
86 | // * Evaluate standard new. |
87 | // * Inline constructor S(). |
88 | // * Bind value for standard new. |
89 | // <- Exit our custom new (nullptr). |
90 | // * Evaluate constructor S(Garbage). |
91 | // * Bind value for our custom new. |
92 | s = new (nullptr) S(ConstructionKind::Garbage); |
93 | clang_analyzer_eval(s->x == 1); // expected-warning{{TRUE}} |
94 | delete s; |
95 | |
96 | // -> Enter our custom new (nullptr). |
97 | // * Evaluate standard new. |
98 | // * Inline constructor S(). |
99 | // * Bind value for standard new. |
100 | // <- Exit our custom new (nullptr). |
101 | // -> Enter constructor S(Recursive). |
102 | // -> Enter our custom new (nullptr). |
103 | // * Evaluate standard new. |
104 | // * Inline constructor S(). |
105 | // * Bind value for standard new. |
106 | // <- Exit our custom new (nullptr). |
107 | // * Evaluate constructor S(5). |
108 | // * Bind value for our custom new (nullptr). |
109 | // * Assign that value to global_s. |
110 | // <- Exit constructor S(Recursive). |
111 | // * Bind value for our custom new (nullptr). |
112 | global_s = nullptr; |
113 | s = new (nullptr) S(ConstructionKind::Recursive); |
114 | clang_analyzer_eval(global_s); // expected-warning{{TRUE}} |
115 | clang_analyzer_eval(global_s->x == 5); // expected-warning{{TRUE}} |
116 | clang_analyzer_eval(s->x == 6); // expected-warning{{TRUE}} |
117 | delete s; |
118 | } |
119 | |