]> granicus.if.org Git - clang/commitdiff
[analyzer] Improve modeling of static initializers.
authorAnna Zaks <ganna@apple.com>
Thu, 19 Nov 2015 01:25:28 +0000 (01:25 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 19 Nov 2015 01:25:28 +0000 (01:25 +0000)
Conversions between unrelated pointer types (e.g. char * and void *) involve
bitcasts which were not properly modeled in case of static initializers. The
patch fixes this problem.

The problem was originally spotted by Artem Dergachev. Patched by Yuri Gribov!

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

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

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

index 4f8ccd0329de899b88e71d95c2bdc5e2a71e4688..98fac33c22ab06e9f052b0248962e80abe3578ab 100644 (file)
@@ -275,11 +275,17 @@ Optional<SVal> SValBuilder::getConstantVal(const Expr *E) {
 
   case Stmt::ImplicitCastExprClass: {
     const CastExpr *CE = cast<CastExpr>(E);
-    if (CE->getCastKind() == CK_ArrayToPointerDecay) {
-      Optional<SVal> ArrayVal = getConstantVal(CE->getSubExpr());
-      if (!ArrayVal)
+    switch (CE->getCastKind()) {
+    default:
+      break;
+    case CK_ArrayToPointerDecay:
+    case CK_BitCast: {
+      const Expr *SE = CE->getSubExpr();
+      Optional<SVal> Val = getConstantVal(SE);
+      if (!Val)
         return None;
-      return evalCast(*ArrayVal, CE->getType(), CE->getSubExpr()->getType());
+      return evalCast(*Val, CE->getType(), SE->getType());
+    }
     }
     // FALLTHROUGH
   }
index 183df16e124d18ffaafea3fe248bb4a0a71f4082..b7962b53a89b2cb1cd7d233f8e2177d9bd4dec69 100644 (file)
@@ -275,7 +275,7 @@ namespace DefaultArgs {
 
     clang_analyzer_eval(defaultReferenceZero(1) == -1); // expected-warning{{TRUE}}
     clang_analyzer_eval(defaultReferenceZero() == 0); // expected-warning{{TRUE}}
-}
+  }
 
   double defaultFloatReference(const double &i = 42) {
     return -i;
@@ -300,6 +300,13 @@ namespace DefaultArgs {
     clang_analyzer_eval(defaultString("xyz") == 'y'); // expected-warning{{TRUE}}
     clang_analyzer_eval(defaultString() == 'b'); // expected-warning{{TRUE}}
   }
+
+  const void * const void_string = "abc";
+
+  void testBitcastedString() {
+    clang_analyzer_eval(0 != void_string); // expected-warning{{TRUE}}
+    clang_analyzer_eval('b' == ((char *)void_string)[1]); // expected-warning{{TRUE}}
+  }
 }
 
 namespace OperatorNew {