1 // RUN: %clang_analyze_cc1 -std=c++11 %s -verify -analyzer-output=text \
2 // RUN: -analyzer-checker=core \
3 // RUN: -analyzer-checker=cplusplus \
4 // RUN: -analyzer-checker=unix.Malloc \
5 // RUN: -analyzer-checker=debug.ExprInspection \
6 // RUN: -analyzer-config eagerly-assume=false
8 extern "C" char *strdup(const char* s
);
9 extern "C" void free(void* ptr
);
12 template<class T
> struct remove_reference
{ typedef T type
; };
13 template<class T
> struct remove_reference
<T
&> { typedef T type
; };
14 template<class T
> struct remove_reference
<T
&&> { typedef T type
; };
15 template<class T
> typename remove_reference
<T
>::type
&& move(T
&& t
);
18 void clang_analyzer_eval(int);
22 StringUsed(const char *s
= "") : str(strdup(s
)) {}
23 StringUsed(const StringUsed
&rhs
) : str(strdup(rhs
.str
)) {}
25 StringUsed
& operator=(const StringUsed
&rhs
);
26 StringUsed
& operator=(StringUsed
&&rhs
);
27 operator const char*() const;
32 StringUsed::~StringUsed() {
36 StringUsed
&StringUsed::operator=(const StringUsed
&rhs
) {
37 // expected-note@-1{{Assuming rhs == *this}}
38 // expected-note@-2{{Assuming rhs == *this}}
39 // expected-note@-3{{Assuming rhs != *this}}
40 clang_analyzer_eval(*this == rhs
); // expected-warning{{TRUE}}
41 // expected-warning@-1{{UNKNOWN}}
42 // expected-note@-2{{TRUE}}
43 // expected-note@-3{{UNKNOWN}}
44 free(str
); // expected-note{{Memory is released}}
45 str
= strdup(rhs
.str
); // expected-warning{{Use of memory after it is freed}}
46 // expected-note@-1{{Use of memory after it is freed}}
47 // expected-note@-2{{Memory is allocated}}
51 StringUsed
&StringUsed::operator=(StringUsed
&&rhs
) {
52 // expected-note@-1{{Assuming rhs == *this}}
53 // expected-note@-2{{Assuming rhs != *this}}
54 clang_analyzer_eval(*this == rhs
); // expected-warning{{TRUE}}
55 // expected-warning@-1{{UNKNOWN}}
56 // expected-note@-2{{TRUE}}
57 // expected-note@-3{{UNKNOWN}}
59 rhs
.str
= nullptr; // expected-warning{{Potential memory leak}}
60 // expected-note@-1{{Potential memory leak}}
64 StringUsed::operator const char*() const {
70 StringUnused(const char *s
= "") : str(strdup(s
)) {}
71 StringUnused(const StringUnused
&rhs
) : str(strdup(rhs
.str
)) {}
73 StringUnused
& operator=(const StringUnused
&rhs
);
74 StringUnused
& operator=(StringUnused
&&rhs
);
75 operator const char*() const;
80 StringUnused::~StringUnused() {
84 StringUnused
&StringUnused::operator=(const StringUnused
&rhs
) {
85 // expected-note@-1{{Assuming rhs == *this}}
86 // expected-note@-2{{Assuming rhs == *this}}
87 // expected-note@-3{{Assuming rhs != *this}}
88 clang_analyzer_eval(*this == rhs
); // expected-warning{{TRUE}}
89 // expected-warning@-1{{UNKNOWN}}
90 // expected-note@-2{{TRUE}}
91 // expected-note@-3{{UNKNOWN}}
92 free(str
); // expected-note{{Memory is released}}
93 str
= strdup(rhs
.str
); // expected-warning{{Use of memory after it is freed}}
94 // expected-note@-1{{Use of memory after it is freed}}
98 StringUnused
&StringUnused::operator=(StringUnused
&&rhs
) {
99 // expected-note@-1{{Assuming rhs == *this}}
100 // expected-note@-2{{Assuming rhs != *this}}
101 clang_analyzer_eval(*this == rhs
); // expected-warning{{TRUE}}
102 // expected-warning@-1{{UNKNOWN}}
103 // expected-note@-2{{TRUE}}
104 // expected-note@-3{{UNKNOWN}}
106 rhs
.str
= nullptr; // FIXME: An improved leak checker should warn here
110 StringUnused::operator const char*() const {
116 StringUsed
s1 ("test"), s2
;
117 s2
= s1
; // expected-note{{Calling copy assignment operator for 'StringUsed'}}
118 // expected-note@-1{{Returned allocated memory}}
119 s2
= std::move(s1
); // expected-note{{Calling move assignment operator for 'StringUsed'}}