From: Gabor Horvath Date: Fri, 4 Dec 2015 15:02:30 +0000 (+0000) Subject: [analyzer] Improve modelling of nullptr_t in the analyzer. Fix PR25414. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2cf6fdb60772ccc586179178c015c9bcdd4194b;p=clang [analyzer] Improve modelling of nullptr_t in the analyzer. Fix PR25414. Differential Revision: http://reviews.llvm.org/D15007 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254718 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/SValBuilder.cpp b/lib/StaticAnalyzer/Core/SValBuilder.cpp index 98fac33c22..cdae04068e 100644 --- a/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -95,6 +95,9 @@ DefinedOrUnknownSVal SValBuilder::getRegionValueSymbolVal(const TypedValueRegion* region) { QualType T = region->getValueType(); + if (T->isNullPtrType()) + return makeZeroVal(T); + if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); @@ -112,6 +115,9 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *SymbolTag, unsigned Count) { QualType T = Ex->getType(); + if (T->isNullPtrType()) + return makeZeroVal(T); + // Compute the type of the result. If the expression is not an R-value, the // result should be a location. QualType ExType = Ex->getType(); @@ -126,6 +132,9 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const void *symbolTag, const LocationContext *LCtx, QualType type, unsigned count) { + if (type->isNullPtrType()) + return makeZeroVal(type); + if (!SymbolManager::canSymbolicate(type)) return UnknownVal(); @@ -142,6 +151,9 @@ DefinedOrUnknownSVal SValBuilder::conjureSymbolVal(const Stmt *stmt, const LocationContext *LCtx, QualType type, unsigned visitCount) { + if (type->isNullPtrType()) + return makeZeroVal(type); + if (!SymbolManager::canSymbolicate(type)) return UnknownVal(); @@ -160,6 +172,8 @@ SValBuilder::getConjuredHeapSymbolVal(const Expr *E, QualType T = E->getType(); assert(Loc::isLocType(T)); assert(SymbolManager::canSymbolicate(T)); + if (T->isNullPtrType()) + return makeZeroVal(T); SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount); return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym)); @@ -185,6 +199,9 @@ SValBuilder::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region) { QualType T = region->getValueType(); + if (T->isNullPtrType()) + return makeZeroVal(T); + if (!SymbolManager::canSymbolicate(T)) return UnknownVal(); diff --git a/test/Analysis/nullptr.cpp b/test/Analysis/nullptr.cpp index 56151dc6b6..17320f3b9a 100644 --- a/test/Analysis/nullptr.cpp +++ b/test/Analysis/nullptr.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -std=c++11 -Wno-conversion-null -analyze -analyzer-checker=core -analyzer-store region -verify %s +// RUN: %clang_cc1 -std=c++11 -Wno-conversion-null -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store region -verify %s + +void clang_analyzer_eval(int); // test to see if nullptr is detected as a null pointer void foo1(void) { @@ -87,3 +89,40 @@ void testMaterializeTemporaryExprWithNullPtr() { // Create MaterializeTemporaryExpr with a nullptr inside. const nullptr_t &r = nullptr; } + +int getSymbol(); + +struct X { + virtual void f() {} +}; + +void invokeF(X* x) { + x->f(); // expected-warning{{Called C++ object pointer is null}} +} + +struct Type { + decltype(nullptr) x; +}; + +void shouldNotCrash() { + decltype(nullptr) p; + if (getSymbol()) + invokeF(p); // expected-warning{{Function call argument is an uninit}} + if (getSymbol()) + invokeF(nullptr); + if (getSymbol()) { + X *x = Type().x; + x->f(); // expected-warning{{Called C++ object pointer is null}} + } +} + +void f(decltype(nullptr) p) { + int *q = nullptr; + clang_analyzer_eval(p == 0); // expected-warning{{TRUE}} + clang_analyzer_eval(q == 0); // expected-warning{{TRUE}} +} + +decltype(nullptr) returnsNullPtrType(); +void fromReturnType() { + ((X *)returnsNullPtrType())->f(); // expected-warning{{Called C++ object pointer is null}} +}