diff options
author | Jordan Rose <jordan_rose@apple.com> | 2013-03-20 20:35:53 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2013-03-20 20:35:53 +0000 |
commit | 5413aaa791c2c35eca1ea041899e1666e8d46602 (patch) | |
tree | 7547b1c188c032583ac4f4b52b34b7d549fec6df /clang/test/Analysis/call-invalidation.cpp | |
parent | 153c81b7c4736de0627e7b885e1d957dbf19cbf4 (diff) | |
download | bcm5719-llvm-5413aaa791c2c35eca1ea041899e1666e8d46602.tar.gz bcm5719-llvm-5413aaa791c2c35eca1ea041899e1666e8d46602.zip |
[analyzer] Invalidate regions indirectly accessible through const pointers.
In this case, the value of 'x' may be changed after the call to indirectAccess:
struct Wrapper {
int *ptr;
};
void indirectAccess(const Wrapper &w);
void test() {
int x = 42;
Wrapper w = { x };
clang_analyzer_eval(x == 42); // TRUE
indirectAccess(w);
clang_analyzer_eval(x == 42); // UNKNOWN
}
This is important for modelling return-by-value objects in C++, to show
that the contents of the struct are escaping in the return copy-constructor.
<rdar://problem/13239826>
llvm-svn: 177570
Diffstat (limited to 'clang/test/Analysis/call-invalidation.cpp')
-rw-r--r-- | clang/test/Analysis/call-invalidation.cpp | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/clang/test/Analysis/call-invalidation.cpp b/clang/test/Analysis/call-invalidation.cpp new file mode 100644 index 00000000000..54281cc98ae --- /dev/null +++ b/clang/test/Analysis/call-invalidation.cpp @@ -0,0 +1,91 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s + +void clang_analyzer_eval(bool); + +void usePointer(int * const *); +void useReference(int * const &); + +void testPointer() { + int x; + int *p; + + p = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + usePointer(&p); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} + + p = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useReference(p); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} + + int * const cp1 = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + usePointer(&cp1); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} + + int * const cp2 = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useReference(cp2); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} +} + + +struct Wrapper { + int *ptr; +}; + +void useStruct(Wrapper &w); +void useConstStruct(const Wrapper &w); + +void testPointerStruct() { + int x; + Wrapper w; + + w.ptr = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useStruct(w); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} + + w.ptr = &x; + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useConstStruct(w); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} +} + + +struct RefWrapper { + int &ref; +}; + +void useStruct(RefWrapper &w); +void useConstStruct(const RefWrapper &w); + +void testReferenceStruct() { + int x; + RefWrapper w = { x }; + + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useStruct(w); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} +} + +// FIXME: This test is split into two functions because region invalidation +// does not preserve reference bindings. <rdar://problem/13320347> +void testConstReferenceStruct() { + int x; + RefWrapper w = { x }; + + x = 42; + clang_analyzer_eval(x == 42); // expected-warning{{TRUE}} + useConstStruct(w); + clang_analyzer_eval(x == 42); // expected-warning{{UNKNOWN}} +} + |