[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