[cfe-commits] r107603 - in /cfe/trunk: lib/Checker/MemRegion.cpp lib/Checker/VLASizeChecker.cpp test/Analysis/outofbound.c

Jordy Rose jediknil at belkadan.com
Sun Jul 4 17:50:15 PDT 2010


Author: jrose
Date: Sun Jul  4 19:50:15 2010
New Revision: 107603

URL: http://llvm.org/viewvc/llvm-project?rev=107603&view=rev
Log:
Track extents for VLAs.

Modified:
    cfe/trunk/lib/Checker/MemRegion.cpp
    cfe/trunk/lib/Checker/VLASizeChecker.cpp
    cfe/trunk/test/Analysis/outofbound.c

Modified: cfe/trunk/lib/Checker/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/MemRegion.cpp?rev=107603&r1=107602&r2=107603&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/MemRegion.cpp (original)
+++ cfe/trunk/lib/Checker/MemRegion.cpp Sun Jul  4 19:50:15 2010
@@ -179,8 +179,9 @@
   ASTContext& Ctx = ValMgr.getContext();
   QualType T = getDesugaredValueType(Ctx);
 
-  // FIXME: Handle variable-length arrays.
-  if (isa<VariableArrayType>(T) || isa<IncompleteArrayType>(T))
+  if (isa<VariableArrayType>(T))
+    return nonloc::SymbolVal(ValMgr.getSymbolManager().getExtentSymbol(this));
+  if (isa<IncompleteArrayType>(T))
     return UnknownVal();
 
   CharUnits Size = Ctx.getTypeSizeInChars(T);

Modified: cfe/trunk/lib/Checker/VLASizeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/VLASizeChecker.cpp?rev=107603&r1=107602&r2=107603&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/VLASizeChecker.cpp (original)
+++ cfe/trunk/lib/Checker/VLASizeChecker.cpp Sun Jul  4 19:50:15 2010
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "GRExprEngineInternalChecks.h"
+#include "clang/AST/CharUnits.h"
 #include "clang/Checker/BugReporter/BugType.h"
 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
 #include "clang/Checker/PathSensitive/GRExprEngine.h"
@@ -42,9 +43,9 @@
   const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
   if (!VD)
     return;
-  
-  const VariableArrayType *VLA
-    = C.getASTContext().getAsVariableArrayType(VD->getType());
+
+  ASTContext &Ctx = C.getASTContext();
+  const VariableArrayType *VLA = Ctx.getAsVariableArrayType(VD->getType());
   if (!VLA)
     return;
 
@@ -70,9 +71,14 @@
     C.EmitReport(report);
     return;
   }
+
+  // See if the size value is known. It can't be undefined because we would have
+  // warned about that already.
+  if (sizeV.isUnknown())
+    return;
   
   // Check if the size is zero.
-  DefinedOrUnknownSVal sizeD = cast<DefinedOrUnknownSVal>(sizeV);
+  DefinedSVal sizeD = cast<DefinedSVal>(sizeV);
 
   const GRState *stateNotZero, *stateZero;
   llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
@@ -92,5 +98,29 @@
   }
  
   // From this point on, assume that the size is not zero.
-  C.addTransition(stateNotZero);
+  state = stateNotZero;
+
+  // Convert the array length to size_t.
+  ValueManager &ValMgr = C.getValueManager();
+  SValuator &SV = ValMgr.getSValuator();
+  QualType SizeTy = Ctx.getSizeType();
+  NonLoc ArrayLength = cast<NonLoc>(SV.EvalCast(sizeD, SizeTy, SE->getType()));
+
+  // Get the element size.
+  CharUnits EleSize = Ctx.getTypeSizeInChars(VLA->getElementType());
+  SVal EleSizeVal = ValMgr.makeIntVal(EleSize.getQuantity(), SizeTy);
+
+  // Multiply the array length by the element size.
+  SVal ArraySizeVal = SV.EvalBinOpNN(state, BinaryOperator::Mul, ArrayLength,
+                                     cast<NonLoc>(EleSizeVal), SizeTy);
+
+  // Finally, Assume that the array's extent matches the given size.
+  const LocationContext *LC = C.getPredecessor()->getLocationContext();
+  DefinedOrUnknownSVal Extent = state->getRegion(VD, LC)->getExtent(ValMgr);
+  DefinedOrUnknownSVal ArraySize = cast<DefinedOrUnknownSVal>(ArraySizeVal);
+  DefinedOrUnknownSVal SizeIsKnown = SV.EvalEQ(state, Extent, ArraySize);
+  state = state->Assume(SizeIsKnown, true);
+
+  // Remember our assumptions!
+  C.addTransition(state);
 }

Modified: cfe/trunk/test/Analysis/outofbound.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/outofbound.c?rev=107603&r1=107602&r2=107603&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/outofbound.c (original)
+++ cfe/trunk/test/Analysis/outofbound.c Sun Jul  4 19:50:15 2010
@@ -54,3 +54,11 @@
   struct three_words a;
   a.c[3] = 1; // expected-warning{{out-of-bound}}
 }
+
+void vla(int a) {
+  if (a == 5) {
+    int x[a];
+    x[4] = 4; // no-warning
+    x[5] = 5; // expected-warning{{out-of-bound}}
+  }
+}





More information about the cfe-commits mailing list