]> granicus.if.org Git - clang/commitdiff
Support sizeof for VLA expressions (sizeof(someVLA)). sizeof(int[n]) still unimplemen...
authorJordy Rose <jediknil@belkadan.com>
Mon, 5 Jul 2010 04:42:43 +0000 (04:42 +0000)
committerJordy Rose <jediknil@belkadan.com>
Mon, 5 Jul 2010 04:42:43 +0000 (04:42 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107611 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Checker/GRExprEngine.cpp
test/Analysis/outofbound.c

index 89b123d1bbe664cfa66a3e7b48df879a07087e05..e5c9bb9eb5bf4b8d974dbfe4713ebc77907d4dff 100644 (file)
@@ -2696,9 +2696,38 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
       // sizeof(void) == 1 byte.
       amt = CharUnits::One();
     }
-    else if (!T.getTypePtr()->isConstantSizeType()) {
-      // FIXME: Add support for VLAs.
-      Dst.Add(Pred);
+    else if (!T->isConstantSizeType()) {
+      assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
+
+      // FIXME: Add support for VLA type arguments, not just VLA expressions.
+      // When that happens, we should probably refactor VLASizeChecker's code.
+      if (Ex->isArgumentType()) {
+        Dst.Add(Pred);
+        return;
+      }
+
+      // Get the size by getting the extent of the sub-expression.
+      // First, visit the sub-expression to find its region.
+      Expr *Arg = Ex->getArgumentExpr();
+      ExplodedNodeSet Tmp;
+      VisitLValue(Arg, Pred, Tmp);
+
+      for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+        const GRState* state = GetState(*I);
+        const MemRegion *MR = state->getSVal(Arg).getAsRegion();
+
+        // If the subexpression can't be resolved to a region, we don't know
+        // anything about its size. Just leave the state as is and continue.
+        if (!MR) {
+          Dst.Add(*I);
+          continue;
+        }
+
+        // The result is the extent of the VLA.
+        SVal Extent = cast<SubRegion>(MR)->getExtent(ValMgr);
+        MakeNode(Dst, Ex, *I, state->BindExpr(Ex, Extent));
+      }
+
       return;
     }
     else if (T->getAs<ObjCObjectType>()) {
index 8ffb3e1efbf2a6c78516ae8e21ea91587622a935..9b487300c88ad74efe7bdf239a81d8f245e1e87b 100644 (file)
@@ -62,3 +62,12 @@ void vla(int a) {
     x[5] = 5; // expected-warning{{out-of-bound}}
   }
 }
+
+void sizeof_vla(int a) {
+  if (a == 5) {
+    char x[a];
+    int y[sizeof(x)];
+    y[4] = 4; // no-warning
+    y[5] = 5; // expected-warning{{out-of-bound}}
+  }
+}