danielmarjamaki created this revision.
danielmarjamaki added reviewers: zaks.anna, dcoughlin.
danielmarjamaki added a subscriber: cfe-commits.
danielmarjamaki set the repository for this revision to rL LLVM.

Example code:

  void f1(int x) {
    int a[20] = {0};
    if (x==25) {}
    if (a[x] == 123) {}  // <- Warning
  }

If I don't enable alpha, only core, then Clang writes this misleading FP:

  undef.c:5:12: warning: The left operand of '==' is a garbage value

I say it's a FP because the message is wrong. If the message correctly said 
"array index out of bounds" and pointed out a[x] directly, then it would be TP. 
This message goes away if alpha is enabled and I believe that is by intention.

Since there is a array-index-out-of-bounds check in alpha I am guessing that 
the UndefinedBinaryOperatorResult should not report "array index out of 
bounds". Therefore I remove this warning from this check.

This patch is a experimental work in progress. I would like to know if you 
think I should modifiy the UndefinedBinaryOperatorResult check or if I should 
do something in the ExprEngine? Maybe array index out of bounds should not lead 
to Undef SVal?

With this patch, all the existing tests succeed.


Repository:
  rL LLVM

https://reviews.llvm.org/D28278

Files:
  lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp


Index: lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -61,7 +61,7 @@
     SmallString<256> sbuf;
     llvm::raw_svector_ostream OS(sbuf);
     const Expr *Ex = nullptr;
-    bool isLeft = true;
+    bool isLeft;
 
     if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
       Ex = B->getLHS()->IgnoreParenCasts();
@@ -73,6 +73,24 @@
     }
 
     if (Ex) {
+      if (isa<ArraySubscriptExpr>(Ex)) {
+        SVal Loc = state->getSVal(Ex,LCtx);
+        if (Loc.isValid()) {
+          const MemRegion *MR = Loc.castAs<loc::MemRegionVal>().getRegion();
+          if (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) {
+            DefinedOrUnknownSVal Idx = 
ER->getIndex().castAs<DefinedOrUnknownSVal>();
+            DefinedOrUnknownSVal NumElements
+              = C.getStoreManager().getSizeInElements(state, 
ER->getSuperRegion(),
+                ER->getValueType());
+            ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, 
true);
+            ProgramStateRef StOutBound = state->assumeInBound(Idx, 
NumElements, false);
+            if (StOutBound && !StInBound) {
+              return;
+            }
+          }
+        }
+      }
+
       OS << "The " << (isLeft ? "left" : "right")
          << " operand of '"
          << BinaryOperator::getOpcodeStr(B->getOpcode())


Index: lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp
@@ -61,7 +61,7 @@
     SmallString<256> sbuf;
     llvm::raw_svector_ostream OS(sbuf);
     const Expr *Ex = nullptr;
-    bool isLeft = true;
+    bool isLeft;
 
     if (state->getSVal(B->getLHS(), LCtx).isUndef()) {
       Ex = B->getLHS()->IgnoreParenCasts();
@@ -73,6 +73,24 @@
     }
 
     if (Ex) {
+      if (isa<ArraySubscriptExpr>(Ex)) {
+        SVal Loc = state->getSVal(Ex,LCtx);
+        if (Loc.isValid()) {
+          const MemRegion *MR = Loc.castAs<loc::MemRegionVal>().getRegion();
+          if (const ElementRegion *ER = dyn_cast<ElementRegion>(MR)) {
+            DefinedOrUnknownSVal Idx = ER->getIndex().castAs<DefinedOrUnknownSVal>();
+            DefinedOrUnknownSVal NumElements
+              = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
+                ER->getValueType());
+            ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true);
+            ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false);
+            if (StOutBound && !StInBound) {
+              return;
+            }
+          }
+        }
+      }
+
       OS << "The " << (isLeft ? "left" : "right")
          << " operand of '"
          << BinaryOperator::getOpcodeStr(B->getOpcode())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to