[analyzer] Improve modelling of nullptr_t in the analyzer. Fix PR25414.

Differential Revision: http://reviews.llvm.org/D15007

llvm-svn: 254718
This commit is contained in:
Gabor Horvath 2015-12-04 15:02:30 +00:00
parent 87cd9c63df
commit e86cb2e822
2 changed files with 57 additions and 1 deletions

View File

@ -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();

View File

@ -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}}
}