diff options
| author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-17 00:42:35 +0000 |
|---|---|---|
| committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-07-17 00:42:35 +0000 |
| commit | 35dbd0b1ff4b9c26a51fa8ae178f8799f3976f67 (patch) | |
| tree | 40a3cb97f0d5c15d29744a46dce0cdb354b0c58a /clang/test | |
| parent | d1163790c363bb47c4b072dc679522941ebf55ca (diff) | |
| download | bcm5719-llvm-35dbd0b1ff4b9c26a51fa8ae178f8799f3976f67.tar.gz bcm5719-llvm-35dbd0b1ff4b9c26a51fa8ae178f8799f3976f67.zip | |
[analyzer] pr37802: Fix symbolic-pointer-to-boolean casts during load.
The canonical representation of pointer &SymRegion{$x} casted to boolean is
"$x != 0", not "$x". Assertion added in r337227 catches that.
Differential Revision: https://reviews.llvm.org/D48232
llvm-svn: 337228
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/Analysis/casts.cpp | 6 | ||||
| -rw-r--r-- | clang/test/Analysis/pr37802.cpp | 106 |
2 files changed, 112 insertions, 0 deletions
diff --git a/clang/test/Analysis/casts.cpp b/clang/test/Analysis/casts.cpp index 6499b20a79d..757eb6da662 100644 --- a/clang/test/Analysis/casts.cpp +++ b/clang/test/Analysis/casts.cpp @@ -35,3 +35,9 @@ int *&&castToIntPtrRValueRef(char *p) { bool testCastToIntPtrRValueRef(char *p, int *s) { return castToIntPtrRValueRef(p) != s; // no-crash } + +bool retrievePointerFromBoolean(int *p) { + bool q; + *reinterpret_cast<int **>(&q) = p; + return q; +} diff --git a/clang/test/Analysis/pr37802.cpp b/clang/test/Analysis/pr37802.cpp new file mode 100644 index 00000000000..647e389362c --- /dev/null +++ b/clang/test/Analysis/pr37802.cpp @@ -0,0 +1,106 @@ +// RUN: %clang_analyze_cc1 -w -analyzer-checker=core -verify %s + +// expected-no-diagnostics + +void *operator new(unsigned long, void *h) { return h; } + +// I've no idea what this code does, but it used to crash, so let's keep it. +namespace pr37802_v1 { +struct J { + int *p; +}; +class X { + void *ar; + +public: + X(void *t) : ar(t) {} + template <typename T> + void f(const T &t) { + new (ar) T(t); + } +}; +class Y { +public: + template <typename T> + void f(T &&); + void f(J t) { + f(*t.p); + } +}; +class Z { + int at() const {} + +public: + Z(const Z &other) { + other.au(X(this)); + } + template <typename T> + void au(T t) const { + void *c = const_cast<Z *>(this); + if (at()) { + t.f(*static_cast<J *>(c)); + } else { + t.f(*static_cast<bool *>(c)); + } + } +}; +Z g() { + Z az = g(); + Z e = az; + Y d; + e.au(d); +} +} // namespace pr37802_v1 + + +// This slightly modified code crashed differently. +namespace pr37802_v2 { +struct J { + int *p; +}; + +class X { + void *ar; + +public: + X(void *t) : ar(t) {} + void f(const J &t) { new (ar) J(t); } + void f(const bool &t) { new (ar) bool(t); } +}; + +class Y { +public: + void boolf(bool &&); + void f(J &&); + void f(J t) { boolf(*t.p); } +}; + +class Z { + int at() const {} + +public: + Z(const Z &other) { other.au(X(this)); } + void au(X t) const { + void *c = const_cast<Z *>(this); + if (at()) { + t.f(*static_cast<J *>(c)); + } else { + t.f(*static_cast<bool *>(c)); + } + } + void au(Y t) const { + void *c = const_cast<Z *>(this); + if (at()) { + t.f(*static_cast<J *>(c)); + } else { + } + } +}; + +Z g() { + Z az = g(); + Z e = az; + Y d; + e.au(d); +} +} // namespace pr37802_v2 |

