]> granicus.if.org Git - clang/commitdiff
[analyzer] Relax an assertion in VisitLvalArraySubscriptExpr
authorAnna Zaks <ganna@apple.com>
Thu, 5 Feb 2015 01:02:59 +0000 (01:02 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 5 Feb 2015 01:02:59 +0000 (01:02 +0000)
The analyzer thinks that ArraySubscriptExpr cannot be an r-value (ever).
However, it can be in some corner cases. Specifically, C forbids expressions
of unqualified void type from being l-values.

Note, the analyzer will keep modeling the subscript expr as an l-value. The
analyzer should be treating void* as a char array
(https://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Pointer-Arith.html).

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

lib/StaticAnalyzer/Core/ExprEngine.cpp
test/Analysis/array-struct.c

index 4699df8819bd58af0d7bc54d5c0a4d5166e9ac64..5cdb7eb0a0ffdea83ee74297109531e982bd29dd 100644 (file)
@@ -1901,6 +1901,9 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
   getCheckerManager().runCheckersForPreStmt(checkerPreStmt, Pred, A, *this);
 
   StmtNodeBuilder Bldr(checkerPreStmt, Dst, *currBldrCtx);
+  assert(A->isGLValue() ||
+          (!AMgr.getLangOpts().CPlusPlus &&
+           A->getType().isCForbiddenLValueType()));
 
   for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(),
                                  ei = checkerPreStmt.end(); it != ei; ++it) {
@@ -1909,7 +1912,6 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A,
     SVal V = state->getLValue(A->getType(),
                               state->getSVal(Idx, LCtx),
                               state->getSVal(Base, LCtx));
-    assert(A->isGLValue());
     Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), nullptr,
                       ProgramPoint::PostLValueKind);
   }
index c22f9796e5806254fc325d8b75b8a193af1121fe..28e09ad2e883cdce5265b4860009d4dc9ef079ae 100644 (file)
@@ -183,3 +183,19 @@ int offset_of_data_array(void)
   return ((char *)&(((struct s*)0)->data_array)) - ((char *)0); // no-warning
 }
 
+int testPointerArithmeticOnVoid(void *bytes) {
+  int p = 0;
+  if (&bytes[0] == &bytes[1])
+    return 6/p; // no-warning
+  return 0;
+}
+
+int testRValueArraySubscriptExpr(void *bytes) {
+  int *p = (int*)&bytes[0];
+  *p = 0;
+  if (*(int*)&bytes[0] == 0)
+    return 0;
+  return 5/(*p); // no-warning
+}
+
+