File: self-assign.cpp

package info (click to toggle)
llvm-toolchain-4.0 1%3A4.0.1-10~deb9u2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 493,332 kB
  • sloc: cpp: 2,698,100; ansic: 552,773; asm: 128,821; python: 121,589; objc: 105,054; sh: 21,174; lisp: 6,758; ml: 5,532; perl: 5,311; pascal: 5,245; makefile: 2,083; cs: 1,868; xml: 686; php: 212; csh: 117
file content (89 lines) | stat: -rw-r--r-- 3,295 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// RUN: %clang_cc1 -std=c++11 -analyze -analyzer-checker=core,cplusplus,unix.Malloc,debug.ExprInspection %s -verify -analyzer-output=text

extern "C" char *strdup(const char* s);
extern "C" void free(void* ptr);

namespace std {
template<class T> struct remove_reference      { typedef T type; };
template<class T> struct remove_reference<T&>  { typedef T type; };
template<class T> struct remove_reference<T&&> { typedef T type; };
template<class T> typename remove_reference<T>::type&& move(T&& t);
}

void clang_analyzer_eval(int);

class StringUsed {
public:
  StringUsed(const char *s = "") : str(strdup(s)) {}
  StringUsed(const StringUsed &rhs) : str(strdup(rhs.str)) {}
  ~StringUsed();
  StringUsed& operator=(const StringUsed &rhs);
  StringUsed& operator=(StringUsed &&rhs);
  operator const char*() const;
private:
  char *str;
};

StringUsed::~StringUsed() {
  free(str);
}

StringUsed& StringUsed::operator=(const StringUsed &rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
  clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
  free(str); // expected-note{{Memory is released}}
  str = strdup(rhs.str); // expected-warning{{Use of memory after it is freed}}  expected-note{{Use of memory after it is freed}}
  return *this;
}

StringUsed& StringUsed::operator=(StringUsed &&rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
  clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
  str = rhs.str;
  rhs.str = nullptr; // FIXME: An improved leak checker should warn here
  return *this;
}

StringUsed::operator const char*() const {
  return str;
}

class StringUnused {
public:
  StringUnused(const char *s = "") : str(strdup(s)) {}
  StringUnused(const StringUnused &rhs) : str(strdup(rhs.str)) {}
  ~StringUnused();
  StringUnused& operator=(const StringUnused &rhs);
  StringUnused& operator=(StringUnused &&rhs);
  operator const char*() const;
private:
  char *str;
};

StringUnused::~StringUnused() {
  free(str);
}

StringUnused& StringUnused::operator=(const StringUnused &rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
  clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
  free(str); // expected-note{{Memory is released}}
  str = strdup(rhs.str); // expected-warning{{Use of memory after it is freed}}  expected-note{{Use of memory after it is freed}}
  return *this;
}

StringUnused& StringUnused::operator=(StringUnused &&rhs) { // expected-note{{Assuming rhs == *this}} expected-note{{Assuming rhs != *this}}
  clang_analyzer_eval(*this == rhs); // expected-warning{{TRUE}} expected-warning{{UNKNOWN}} expected-note{{TRUE}} expected-note{{UNKNOWN}}
  str = rhs.str;
  rhs.str = nullptr; // FIXME: An improved leak checker should warn here
  return *this;
}

StringUnused::operator const char*() const {
  return str;
}


int main() {
  StringUsed s1 ("test"), s2;
  s2 = s1;
  s2 = std::move(s1);
  return 0;
}