]> granicus.if.org Git - clang/commitdiff
[analyzer] Improve modelling of nullptr_t in the analyzer. Fix PR25414.
authorGabor Horvath <xazax.hun@gmail.com>
Fri, 4 Dec 2015 15:02:30 +0000 (15:02 +0000)
committerGabor Horvath <xazax.hun@gmail.com>
Fri, 4 Dec 2015 15:02:30 +0000 (15:02 +0000)
Differential Revision: http://reviews.llvm.org/D15007

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@254718 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/SValBuilder.cpp
test/Analysis/nullptr.cpp

index 98fac33c22ab06e9f052b0248962e80abe3578ab..cdae04068e1d1e3247ba514b94caa1705490b9b6 100644 (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();
 
index 56151dc6b65079afad24492acc8b6e08074dddbe..17320f3b9a84b4c0a2e62286e7719716c09ea446 100644 (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}}
+}