summaryrefslogtreecommitdiff
path: root/test/Analysis/inner-pointer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/inner-pointer.cpp')
-rw-r--r--test/Analysis/inner-pointer.cpp316
1 files changed, 175 insertions, 141 deletions
diff --git a/test/Analysis/inner-pointer.cpp b/test/Analysis/inner-pointer.cpp
index 230e3396c59ea..81b750d7e5dd3 100644
--- a/test/Analysis/inner-pointer.cpp
+++ b/test/Analysis/inner-pointer.cpp
@@ -1,43 +1,9 @@
-//RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer %s -analyzer-output=text -verify
+// RUN: %clang_analyze_cc1 -analyzer-checker=cplusplus.InnerPointer \
+// RUN: %s -analyzer-output=text -verify
+#include "Inputs/system-header-simulator-cxx.h"
namespace std {
-typedef int size_type;
-
-template <typename CharT>
-class basic_string {
-public:
- basic_string();
- basic_string(const CharT *s);
-
- ~basic_string();
- void clear();
-
- basic_string &operator=(const basic_string &str);
- basic_string &operator+=(const basic_string &str);
-
- const CharT *c_str() const;
- const CharT *data() const;
- CharT *data();
-
- basic_string &append(size_type count, CharT ch);
- basic_string &assign(size_type count, CharT ch);
- basic_string &erase(size_type index, size_type count);
- basic_string &insert(size_type index, size_type count, CharT ch);
- basic_string &replace(size_type pos, size_type count, const basic_string &str);
- void pop_back();
- void push_back(CharT ch);
- void reserve(size_type new_cap);
- void resize(size_type count);
- void shrink_to_fit();
- void swap(basic_string &other);
-};
-
-typedef basic_string<char> string;
-typedef basic_string<wchar_t> wstring;
-typedef basic_string<char16_t> u16string;
-typedef basic_string<char32_t> u32string;
-
template <typename T>
void func_ref(T &a);
@@ -65,10 +31,10 @@ void deref_after_scope_char(bool cond) {
const char *c, *d;
{
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s;
const char *c2 = s.c_str();
if (cond) {
@@ -76,11 +42,11 @@ void deref_after_scope_char(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
}
@@ -88,22 +54,22 @@ void deref_after_scope_char_data_non_const() {
char *c;
{
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s;
char *c2 = s.data();
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_wchar_t(bool cond) {
const wchar_t *c, *d;
{
std::wstring s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
+ d = s.data(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
+ } // expected-note {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
std::wstring s;
const wchar_t *c2 = s.c_str();
if (cond) {
@@ -111,11 +77,11 @@ void deref_after_scope_wchar_t(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
}
@@ -123,36 +89,36 @@ void deref_after_scope_char16_t_cstr() {
const char16_t *c16;
{
std::u16string s16;
- c16 = s16.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c16 = s16.c_str(); // expected-note {{Pointer to inner buffer of 'std::u16string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::u16string' deallocated by call to destructor}}
std::u16string s16;
const char16_t *c16_2 = s16.c_str();
- consume(c16); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c16); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_char32_t_data() {
const char32_t *c32;
{
std::u32string s32;
- c32 = s32.data(); // expected-note {{Dangling inner pointer obtained here}}
- } // expected-note {{Inner pointer invalidated by call to destructor}}
+ c32 = s32.data(); // expected-note {{Pointer to inner buffer of 'std::u32string' obtained here}}
+ } // expected-note {{Inner buffer of 'std::u32string' deallocated by call to destructor}}
std::u32string s32;
const char32_t *c32_2 = s32.data();
- consume(c32); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c32); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void multiple_symbols(bool cond) {
const char *c1, *d1;
{
std::string s1;
- c1 = s1.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- d1 = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
+ c1 = s1.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ d1 = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
const char *local = s1.c_str();
consume(local); // no-warning
- } // expected-note {{Inner pointer invalidated by call to destructor}}
- // expected-note@-1 {{Inner pointer invalidated by call to destructor}}
+ } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
std::string s2;
const char *c2 = s2.c_str();
if (cond) {
@@ -160,11 +126,11 @@ void multiple_symbols(bool cond) {
// expected-note@-2 {{Taking true branch}}
// expected-note@-3 {{Assuming 'cond' is 0}}
// expected-note@-4 {{Taking false branch}}
- consume(c1); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ consume(c1); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
} else {
- consume(d1); // expected-warning {{Use of memory after it is freed}}
- } // expected-note@-1 {{Use of memory after it is freed}}
+ consume(d1); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ } // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_scope_ok(bool cond) {
@@ -183,127 +149,159 @@ void deref_after_scope_ok(bool cond) {
void deref_after_equals() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s = "world"; // expected-note {{Inner pointer invalidated by call to 'operator='}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s = "world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator='}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_plus_equals() {
const char *c;
std::string s = "hello";
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s += " world"; // expected-note {{Inner pointer invalidated by call to 'operator+='}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s += " world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator+='}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_clear() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.clear(); // expected-note {{Inner pointer invalidated by call to 'clear'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_append() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.append(2, 'x'); // expected-note {{Inner pointer invalidated by call to 'append'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.append(2, 'x'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'append'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_assign() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.assign(4, 'a'); // expected-note {{Inner pointer invalidated by call to 'assign'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.assign(4, 'a'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'assign'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_erase() {
const char *c;
std::string s = "hello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.erase(0, 2); // expected-note {{Inner pointer invalidated by call to 'erase'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.erase(0, 2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'erase'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_insert() {
const char *c;
std::string s = "ello";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.insert(0, 1, 'h'); // expected-note {{Inner pointer invalidated by call to 'insert'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.insert(0, 1, 'h'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'insert'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_replace() {
const char *c;
std::string s = "hello world";
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.replace(6, 5, "string"); // expected-note {{Inner pointer invalidated by call to 'replace'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.replace(6, 5, "string"); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'replace'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_pop_back() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.pop_back(); // expected-note {{Inner pointer invalidated by call to 'pop_back'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.pop_back(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'pop_back'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_push_back() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.push_back('c'); // expected-note {{Inner pointer invalidated by call to 'push_back'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.push_back('c'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'push_back'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_reserve() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- s.reserve(5); // expected-note {{Inner pointer invalidated by call to 'reserve'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.reserve(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'reserve'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_resize() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.resize(5); // expected-note {{Inner pointer invalidated by call to 'resize'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.resize(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'resize'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_shrink_to_fit() {
const char *c;
std::string s;
- c = s.data(); // expected-note {{Dangling inner pointer obtained here}}
- s.shrink_to_fit(); // expected-note {{Inner pointer invalidated by call to 'shrink_to_fit'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s.shrink_to_fit(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'shrink_to_fit'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void deref_after_swap() {
const char *c;
std::string s1, s2;
- c = s1.data(); // expected-note {{Dangling inner pointer obtained here}}
- s1.swap(s2); // expected-note {{Inner pointer invalidated by call to 'swap'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ s1.swap(s2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'swap'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+struct S {
+ std::string s;
+ const char *name() {
+ return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Pointer to inner buffer of 'std::string' obtained here}}
+ }
+ void clear() {
+ s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
+ }
+ ~S() {} // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
+};
+
+void cleared_through_method() {
+ S x;
+ const char *c = x.name(); // expected-note {{Calling 'S::name'}}
+ // expected-note@-1 {{Returning from 'S::name'}}
+ x.clear(); // expected-note {{Calling 'S::clear'}}
+ // expected-note@-1 {{Returning; inner buffer was reallocated}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+void destroyed_through_method() {
+ S y;
+ const char *c = y.name(); // expected-note {{Calling 'S::name'}}
+ // expected-note@-1 {{Returning from 'S::name'}}
+ y.~S(); // expected-note {{Calling '~S'}}
+ // expected-note@-1 {{Returning; inner buffer was deallocated}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
//=---------------------------=//
@@ -313,10 +311,10 @@ void deref_after_swap() {
void STL_func_ref() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- std::func_ref(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ std::func_ref(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void STL_func_const_ref() {
@@ -339,10 +337,10 @@ void func_ptr_known() {
const char *c;
std::string s;
void (*func_ptr)(std::string &) = std::func_ref<std::string>;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- func_ptr(s); // expected-note {{Inner pointer invalidated by call to 'func_ref'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ func_ptr(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
}
void func_ptr_unknown(void (*func_ptr)(std::string &)) {
@@ -356,8 +354,44 @@ void func_ptr_unknown(void (*func_ptr)(std::string &)) {
void func_default_arg() {
const char *c;
std::string s;
- c = s.c_str(); // expected-note {{Dangling inner pointer obtained here}}
- default_arg(3, s); // expected-note {{Inner pointer invalidated by call to 'default_arg'}}
- consume(c); // expected-warning {{Use of memory after it is freed}}
- // expected-note@-1 {{Use of memory after it is freed}}
+ c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ default_arg(3, s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'default_arg'}}
+ consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
+}
+
+struct T {
+ std::string to_string() { return s; }
+private:
+ std::string s;
+};
+
+const char *escape_via_return_temp() {
+ T x;
+ return x.to_string().c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
+}
+
+const char *escape_via_return_local() {
+ std::string s;
+ return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
+ // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
+ // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
+ // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
+}
+
+
+char *c();
+class A {};
+
+void no_CXXRecordDecl() {
+ A a, *b;
+ *(void **)&b = c() + 1;
+ *b = a; // no-crash
+}
+
+void checkReference(std::string &s) {
+ const char *c = s.c_str();
}