]> granicus.if.org Git - clang/commitdiff
RegionStore: specially handle loads from integer global variables declared 'const'.
authorTed Kremenek <kremenek@apple.com>
Tue, 30 Mar 2010 20:31:04 +0000 (20:31 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 30 Mar 2010 20:31:04 +0000 (20:31 +0000)
Fixes a false positive reported in PR 6288.

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

lib/Checker/RegionStore.cpp
test/Analysis/misc-ps-region-store.m

index 26d33f6588bab9a7025aada1048235fb158c7f53..d590a86a81cbaf4af602ce8fdd1d3d40f217cf4d 100644 (file)
@@ -1313,8 +1313,23 @@ SVal RegionStoreManager::RetrieveVar(Store store, const VarRegion *R) {
     return ValMgr.getRegionValueSymbolVal(R);
 
   if (isa<GlobalsSpaceRegion>(MS)) {
-    if (VD->isFileVarDecl())
+    if (VD->isFileVarDecl()) {
+      // Is 'VD' declared constant?  If so, retrieve the constant value.
+      QualType CT = Ctx.getCanonicalType(T);
+      if (CT.isConstQualified()) {
+        const Expr *Init = VD->getInit();
+        // Do the null check first, as we want to call 'IgnoreParenCasts'.
+        if (Init)
+          if (const IntegerLiteral *IL =
+              dyn_cast<IntegerLiteral>(Init->IgnoreParenCasts())) {
+            const nonloc::ConcreteInt &V = ValMgr.makeIntVal(IL);
+            return ValMgr.getSValuator().EvalCast(V, Init->getType(),
+                                                  IL->getType());
+          }
+      }
+
       return ValMgr.getRegionValueSymbolVal(R);
+    }
 
     if (T->isIntegerType())
       return ValMgr.makeIntVal(0, T);
index b95d82f76330d498848ea161713ab9accf5f6fba..d10b9fa5ded78a7ba0031eca6385b09ecefacd0b 100644 (file)
@@ -920,3 +920,38 @@ void pr6302(id x, Class y) {
   // This previously crashed the analyzer (reported in PR 6302)
   x->isa  = y;
 }
+
+//===----------------------------------------------------------------------===//
+// Specially handle global variables that are declared constant.  In the
+// example below, this forces the loop to take exactly 2 iterations.
+//===----------------------------------------------------------------------===//
+
+const int pr6288_L_N = 2;
+void pr6288_(void) {
+  int x[2];
+  int *px[2];
+  int i;
+  for (i = 0; i < pr6288_L_N; i++)
+    px[i] = &x[i];
+  *(px[0]) = 0; // no-warning
+}
+
+void pr6288_pos(int z) {
+  int x[2];
+  int *px[2];
+  int i;
+  for (i = 0; i < z; i++)
+    px[i] = &x[i]; // expected-warning{{Access out-of-bound array element (buffer overflow)}}
+  *(px[0]) = 0; // expected-warning{{Dereference of undefined pointer value}}
+}
+
+void pr6288_b(void) {
+  const int L_N = 2;
+  int x[2];
+  int *px[2];
+  int i;
+  for (i = 0; i < L_N; i++)
+    px[i] = &x[i];
+  *(px[0]) = 0; // no-warning
+}
+