NoQ created this revision. NoQ added reviewers: dcoughlin, xazax.hun, a.sidorin, george.karpenkov, szepet, rnkovacs. Herald added subscribers: cfe-commits, mikhail.ramalho, baloghadamsoftware.
The canonical way to represent the result of casting `&SymRegion{$x}` to `bool` is `($x != 0)`, not `$x`. In fact `$x` is an ill-formed `SVal` (when`$x` is a loc-type symbol) and it gets caught by https://reviews.llvm.org/D48205. Fix the cast procedure. Because our cast code is a spaghetti, the code that was fixed was in fact executed very rarely, because there's a duplicate guard in `evalCast()` that's written correctly. But when `evalCastFromLoc()` is called directly (eg., from `CastRetrievedVal()`), this becomes a problem. Repository: rC Clang https://reviews.llvm.org/D48232 Files: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp test/Analysis/casts.cpp test/Analysis/pr37802.cpp
Index: test/Analysis/pr37802.cpp =================================================================== --- /dev/null +++ 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 Index: test/Analysis/casts.cpp =================================================================== --- test/Analysis/casts.cpp +++ test/Analysis/casts.cpp @@ -35,3 +35,9 @@ 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; +} Index: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp =================================================================== --- lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -159,7 +159,8 @@ 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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits