diff options
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp | 3 | ||||
-rw-r--r-- | clang/test/Analysis/casts.cpp | 6 | ||||
-rw-r--r-- | clang/test/Analysis/pr37802.cpp | 106 |
3 files changed, 114 insertions, 1 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp index c08cbb09ba8..7163e380e6c 100644 --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -159,7 +159,8 @@ SVal SimpleSValBuilder::evalCastFromLoc(Loc val, QualType castTy) { return nonloc::SymbolVal(SymMgr.getExtentSymbol(FTR)); if (const SymbolicRegion *SymR = R->getSymbolicBase()) - return nonloc::SymbolVal(SymR->getSymbol()); + return makeNonLoc(SymR->getSymbol(), BO_NE, + BasicVals.getZeroWithPtrWidth(), castTy); // FALL-THROUGH LLVM_FALLTHROUGH; 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 |