<div dir="ltr">It looks like this commit has introduced an assertion failure. See <a href="https://bugs.llvm.org/show_bug.cgi?id=37357">https://bugs.llvm.org/show_bug.cgi?id=37357</a>.</div><br><div class="gmail_quote"><div dir="ltr">On Fri, May 4, 2018 at 10:56 PM Artem Dergachev via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dergachev<br>
Date: Fri May  4 13:52:39 2018<br>
New Revision: 331556<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=331556&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=331556&view=rev</a><br>
Log:<br>
[analyzer] Treat more const variables and fields as known contants.<br>
<br>
When loading from a variable or a field that is declared as constant,<br>
the analyzer will try to inspect its initializer and constant-fold it.<br>
Upon success, the analyzer would skip normal load and return the respective<br>
constant.<br>
<br>
The new behavior also applies to fields/elements of brace-initialized structures<br>
and arrays.<br>
<br>
Patch by Rafael Stahl!<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D45774" rel="noreferrer" target="_blank">https://reviews.llvm.org/D45774</a><br>
<br>
Added:<br>
    cfe/trunk/test/Analysis/globals.cpp<br>
Modified:<br>
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp<br>
    cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp<br>
<br>
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=331556&r1=331555&r2=331556&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=331556&r1=331555&r2=331556&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri May  4 13:52:39 2018<br>
@@ -1606,7 +1606,7 @@ SVal RegionStoreManager::getBindingForEl<br>
   const MemRegion* superR = R->getSuperRegion();<br>
<br>
   // Check if the region is an element region of a string literal.<br>
-  if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) {<br>
+  if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {<br>
     // FIXME: Handle loads from strings where the literal is treated as<br>
     // an integer, e.g., *((unsigned int*)"hello")<br>
     QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();<br>
@@ -1629,6 +1629,27 @@ SVal RegionStoreManager::getBindingForEl<br>
       char c = (i >= length) ? '\0' : Str->getCodeUnit(i);<br>
       return svalBuilder.makeIntVal(c, T);<br>
     }<br>
+  } else if (const VarRegion *VR = dyn_cast<VarRegion>(superR)) {<br>
+    // Check if the containing array is const and has an initialized value.<br>
+    const VarDecl *VD = VR->getDecl();<br>
+    // Either the array or the array element has to be const.<br>
+    if (VD->getType().isConstQualified() || R->getElementType().isConstQualified()) {<br>
+      if (const Expr *Init = VD->getInit()) {<br>
+        if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {<br>
+          // The array index has to be known.<br>
+          if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {<br>
+            int64_t i = CI->getValue().getSExtValue();<br>
+            // Return unknown value if index is out of bounds.<br>
+            if (i < 0 || i >= InitList->getNumInits())<br>
+              return UnknownVal();<br>
+<br>
+            if (const Expr *ElemInit = InitList->getInit(i))<br>
+              if (Optional<SVal> V = svalBuilder.getConstantVal(ElemInit))<br>
+                return *V;<br>
+          }<br>
+        }<br>
+      }<br>
+    }<br>
   }<br>
<br>
   // Check for loads from a code text region.  For such loads, just give up.<br>
@@ -1678,7 +1699,28 @@ SVal RegionStoreManager::getBindingForFi<br>
   if (const Optional<SVal> &V = B.getDirectBinding(R))<br>
     return *V;<br>
<br>
-  QualType Ty = R->getValueType();<br>
+  // Is the field declared constant and has an in-class initializer?<br>
+  const FieldDecl *FD = R->getDecl();<br>
+  QualType Ty = FD->getType();<br>
+  if (Ty.isConstQualified())<br>
+    if (const Expr *Init = FD->getInClassInitializer())<br>
+      if (Optional<SVal> V = svalBuilder.getConstantVal(Init))<br>
+        return *V;<br>
+<br>
+  // If the containing record was initialized, try to get its constant value.<br>
+  const MemRegion* superR = R->getSuperRegion();<br>
+  if (const auto *VR = dyn_cast<VarRegion>(superR)) {<br>
+    const VarDecl *VD = VR->getDecl();<br>
+    QualType RecordVarTy = VD->getType();<br>
+    // Either the record variable or the field has to be const qualified.<br>
+    if (RecordVarTy.isConstQualified() || Ty.isConstQualified())<br>
+      if (const Expr *Init = VD->getInit())<br>
+        if (const auto *InitList = dyn_cast<InitListExpr>(Init))<br>
+          if (const Expr *FieldInit = InitList->getInit(FD->getFieldIndex()))<br>
+            if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))<br>
+              return *V;<br>
+  }<br>
+<br>
   return getBindingForFieldOrElementCommon(B, R, Ty);<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=331556&r1=331555&r2=331556&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp?rev=331556&r1=331555&r2=331556&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp (original)<br>
+++ cfe/trunk/lib/StaticAnalyzer/Core/SValBuilder.cpp Fri May  4 13:52:39 2018<br>
@@ -119,7 +119,7 @@ SValBuilder::getRegionValueSymbolVal(con<br>
<br>
   if (T->isNullPtrType())<br>
     return makeZeroVal(T);<br>
-  <br>
+<br>
   if (!SymbolManager::canSymbolicate(T))<br>
     return UnknownVal();<br>
<br>
@@ -328,12 +328,19 @@ Optional<SVal> SValBuilder::getConstantV<br>
   case Stmt::CXXNullPtrLiteralExprClass:<br>
     return makeNull();<br>
<br>
+  case Stmt::CStyleCastExprClass:<br>
+  case Stmt::CXXFunctionalCastExprClass:<br>
+  case Stmt::CXXConstCastExprClass:<br>
+  case Stmt::CXXReinterpretCastExprClass:<br>
+  case Stmt::CXXStaticCastExprClass:<br>
   case Stmt::ImplicitCastExprClass: {<br>
     const auto *CE = cast<CastExpr>(E);<br>
     switch (CE->getCastKind()) {<br>
     default:<br>
       break;<br>
     case CK_ArrayToPointerDecay:<br>
+    case CK_IntegralToPointer:<br>
+    case CK_NoOp:<br>
     case CK_BitCast: {<br>
       const Expr *SE = CE->getSubExpr();<br>
       Optional<SVal> Val = getConstantVal(SE);<br>
<br>
Added: cfe/trunk/test/Analysis/globals.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/globals.cpp?rev=331556&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/globals.cpp?rev=331556&view=auto</a><br>
==============================================================================<br>
--- cfe/trunk/test/Analysis/globals.cpp (added)<br>
+++ cfe/trunk/test/Analysis/globals.cpp Fri May  4 13:52:39 2018<br>
@@ -0,0 +1,111 @@<br>
+// RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s<br>
+<br>
+<br>
+static const unsigned long long scull = 0;<br>
+void static_int()<br>
+{<br>
+    *(int*)scull = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+const unsigned long long cull = 0;<br>
+void const_int()<br>
+{<br>
+    *(int*)cull = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+static int * const spc = 0;<br>
+void static_ptr()<br>
+{<br>
+    *spc = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const pc = 0;<br>
+void const_ptr()<br>
+{<br>
+    *pc = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+const unsigned long long cull_nonnull = 4;<br>
+void nonnull_int()<br>
+{<br>
+    *(int*)(cull_nonnull - 4) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const pc_nonnull = (int*)sizeof(int);<br>
+void nonnull_ptr()<br>
+{<br>
+    *(pc_nonnull - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const constcast = const_cast<int * const>((int*)sizeof(int));<br>
+void cast1()<br>
+{<br>
+    *(constcast - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const recast = reinterpret_cast<int*>(sizeof(int));<br>
+void cast2()<br>
+{<br>
+    *(recast - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const staticcast = static_cast<int * const>((int*)sizeof(int));<br>
+void cast3()<br>
+{<br>
+    *(staticcast - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+struct Foo { int a; };<br>
+Foo * const dyncast = dynamic_cast<Foo * const>((Foo*)sizeof(Foo));<br>
+void cast4()<br>
+{<br>
+    // Do not handle dynamic_cast for now, because it may change the pointer value.<br>
+    (dyncast - 1)->a = 0; // no-warning<br>
+}<br>
+<br>
+typedef int * const intptrconst;<br>
+int * const funccast = intptrconst(sizeof(int));<br>
+void cast5()<br>
+{<br>
+    *(funccast - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+struct S1<br>
+{<br>
+    int * p;<br>
+};<br>
+const S1 s1 = {<br>
+    .p = (int*)sizeof(int)<br>
+};<br>
+void conststruct()<br>
+{<br>
+    *(s1.p - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+struct S2<br>
+{<br>
+    int * const p;<br>
+};<br>
+S2 s2 = {<br>
+    .p = (int*)sizeof(int)<br>
+};<br>
+void constfield()<br>
+{<br>
+    *(s2.p - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+int * const parr[1] = { (int*)sizeof(int) };<br>
+void constarr()<br>
+{<br>
+    *(parr[0] - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
+<br>
+struct S3<br>
+{<br>
+    int * p = (int*)sizeof(int);<br>
+};<br>
+void recordinit()<br>
+{<br>
+    S3 s3;<br>
+    *(s3.p - 1) = 0; // expected-warning{{Dereference of null pointer}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>