[PATCH] D12251: Analyzer: Calculate field offset correctly

Ismail Pazarbasi via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 30 09:59:54 PDT 2015


ismailp updated this revision to Diff 36123.
ismailp added a comment.

- Don't try to calculate field offset for Objective-C instance variables
- Added test for Objective-C instance variables
- Added a non-null pointer in test


http://reviews.llvm.org/D12251

Files:
  lib/StaticAnalyzer/Core/Store.cpp
  test/Analysis/array-struct-region.cpp
  test/Analysis/ivars.m

Index: test/Analysis/ivars.m
===================================================================
--- test/Analysis/ivars.m
+++ test/Analysis/ivars.m
@@ -138,3 +138,8 @@
   int *x = &obj->uniqueID;
   return *x; // expected-warning{{Dereference of null pointer (loaded from variable 'x')}}
 }
+
+void testFieldOffset() {
+  int *v = &((Root *)0x10)->uniqueID;
+  (void)v;
+}
Index: test/Analysis/array-struct-region.cpp
===================================================================
--- test/Analysis/array-struct-region.cpp
+++ test/Analysis/array-struct-region.cpp
@@ -106,6 +106,28 @@
 #endif
 }
 
+struct FieldOffset {
+  int firstField;
+  char secondField[63];
+  void *thirdField;
+};
+
+void testFieldOffsets() {
+  struct FieldOffset FO;
+  struct FieldOffset *PFONull = 0;
+  struct FieldOffset *PFOConstant = (struct FieldOffset *) 0x22;
+#if __cplusplus
+  struct FieldOffset *PFONew = new struct FieldOffset;
+#endif
+  clang_analyzer_eval((void *)&FO.secondField != (void*)&FO); // expected-warning{{TRUE}}
+  clang_analyzer_eval((void *)&FO.secondField != (void*)&FO.thirdField); // expected-warning{{TRUE}}
+  clang_analyzer_eval((void *)&PFONull->secondField != (void *)&PFONull->thirdField); // expected-warning{{FALSE}}
+  clang_analyzer_eval((void *)&PFONull->secondField == (void *)0); // expected-warning{{TRUE}}
+  clang_analyzer_eval((void *)&PFOConstant->secondField != (void*)PFOConstant); // expected-warning{{TRUE}}
+#if __cplusplus
+  clang_analyzer_eval((void *)&PFONew->secondField != (void *)&PFONew); // expected-warning{{TRUE}}
+#endif
+}
 
 //--------------------
 // C++-only tests
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -15,6 +15,7 @@
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
 
@@ -401,12 +402,23 @@
     // These are anormal cases. Flag an undefined value.
     return UndefinedVal();
 
-  case loc::ConcreteIntKind:
-    // While these seem funny, this can happen through casts.
-    // FIXME: What we should return is the field offset.  For example,
-    //  add the field offset to the integer value.  That way funny things
-    //  like this work properly:  &(((struct foo *) 0xa)->f)
+  case loc::ConcreteIntKind: {
+    // Don't allow field offset calculations, if base is null.
+    if (!Base.isZeroConstant()) {
+      if (const auto *FD = dyn_cast<const FieldDecl>(D)) {
+        if (FD->getKind() != Decl::ObjCIvar) {
+          ASTContext &Ctx = D->getASTContext();
+          CharUnits CU = Ctx.toCharUnitsFromBits(Ctx.getFieldOffset(FD));
+          loc::ConcreteInt BasePtr = BaseL.castAs<loc::ConcreteInt>();
+          llvm::APSInt Offset(Ctx.getTypeSize(Ctx.VoidPtrTy));
+          Offset = CU.getQuantity();
+          Offset += BasePtr.getValue();
+          return svalBuilder.makeIntLocVal(Offset);
+        }
+      }
+    }
     return Base;
+  }
 
   default:
     llvm_unreachable("Unhandled Base.");


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D12251.36123.patch
Type: text/x-patch
Size: 3273 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150930/6cb73b17/attachment.bin>


More information about the cfe-commits mailing list