[PATCH] D12251: Analyzer: Calculate field offset correctly

Ismail Pazarbasi via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 21 15:12:26 PDT 2015


ismailp created this revision.
ismailp added reviewers: krememek, zaks.anna.
ismailp added a subscriber: cfe-commits.

`StoreManager::getLValueFieldOrIvar` should return loc as
base + field-offset, instead of just base.

http://reviews.llvm.org/D12251

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

Index: test/Analysis/array-struct-region.cpp
===================================================================
--- test/Analysis/array-struct-region.cpp
+++ test/Analysis/array-struct-region.cpp
@@ -106,6 +106,26 @@
 #endif
 }
 
+struct FieldOffset {
+  int firstField;
+  char secondField[63];
+  void *thirdField;
+};
+
+void testFieldOffsets() {
+  struct FieldOffset FO;
+  struct FieldOffset *PFONull = 0;
+#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}}
+#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,21 @@
     // 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 FieldDecl *FD = dyn_cast<const FieldDecl>(D)) {
+        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.32871.patch
Type: text/x-patch
Size: 2656 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20150821/b04e1cb5/attachment.bin>


More information about the cfe-commits mailing list