From 8b5a5f304a97afc41b5d6753c989d31d8fdb0e8c Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Thu, 5 Feb 2015 01:02:59 +0000 Subject: [PATCH] [analyzer] Relax an assertion in VisitLvalArraySubscriptExpr 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 | 4 +++- test/Analysis/array-struct.c | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 4699df8819..5cdb7eb0a0 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -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); } diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c index c22f9796e5..28e09ad2e8 100644 --- a/test/Analysis/array-struct.c +++ b/test/Analysis/array-struct.c @@ -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 +} + + -- 2.50.1