[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-02-09 Thread Phabricator via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL324790: [analyzer] Add missing pre-post-statement callbacks 
for OffsetOfExpr. (authored by dergachev, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D42300?vs=133421=133721#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D42300

Files:
  cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
  cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
  cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
  cfe/trunk/test/Analysis/offsetofexpr-callback.c


Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
===
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
@@ -110,4 +110,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
\ No newline at end of file
Index: cfe/trunk/test/Analysis/offsetofexpr-callback.c
===
--- cfe/trunk/test/Analysis/offsetofexpr-callback.c
+++ cfe/trunk/test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder 
-analyzer-config 
debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true
 %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+  char c;
+};
+
+void test() {
+  offsetof(struct S, c); 
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
\ No newline at end of file
Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1543,12 +1543,19 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNode *Node : PreVisit)
+VisitOffsetOfExpr(cast(S), Node, PostVisit);
+
+  getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
   Bldr.addNodes(Dst);
   break;
-
+}
 case Stmt::UnaryExprOrTypeTraitExprClass:
   Bldr.takeNodes(Pred);
   VisitUnaryExprOrTypeTraitExpr(cast(S),
Index: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===
--- cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -33,6 +33,8 @@
  check::PostStmt,
  check::PreStmt,
  check::PostStmt,
+ check::PreStmt,
+ check::PostStmt,
  check::PreCall,
  check::PostCall,
  check::NewAllocator,
@@ -91,6 +93,16 @@
   llvm::errs() << "PostStmt\n";
   }
 
+  void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
+  llvm::errs() << "PreStmt\n";
+  }
+
+  void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
+  llvm::errs() << "PostStmt\n";
+  }
+
   void checkPreCall(const CallEvent , CheckerContext ) const {
 if (isCallbackEnabled(C, "PreCall")) {
   llvm::errs() << "PreCall";


Index: cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
===
--- cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
+++ cfe/trunk/test/Analysis/Inputs/system-header-simulator.h
@@ -110,4 +110,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
\ No newline at end of file
Index: cfe/trunk/test/Analysis/offsetofexpr-callback.c
===
--- cfe/trunk/test/Analysis/offsetofexpr-callback.c
+++ cfe/trunk/test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+  char c;
+};
+
+void test() {
+  offsetof(struct S, c); 
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
\ No newline at end of file
Index: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp

[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-02-08 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ accepted this revision.
NoQ added a comment.
This revision is now accepted and ready to land.

All right, i guess we already do have a pair of callbacks for `IntegerLiteral` 
and it doesn't hurt, especially because here they'd eventually be actually 
useful. I think it should land, just to make it easier to add the actual 
support later.


Repository:
  rC Clang

https://reviews.llvm.org/D42300



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-02-08 Thread Henry Wong via Phabricator via cfe-commits
MTC added a comment.

@NoQ Sorry to bother you again. It seems that this patch is useless to analyzer 
temporarily, if you think so, I will abandon it : ).


Repository:
  rC Clang

https://reviews.llvm.org/D42300



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-02-08 Thread Henry Wong via Phabricator via cfe-commits
MTC updated this revision to Diff 133421.
MTC added a comment.
Herald added a reviewer: george.karpenkov.

rebase


Repository:
  rC Clang

https://reviews.llvm.org/D42300

Files:
  lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/Analysis/Inputs/system-header-simulator.h
  test/Analysis/offsetofexpr-callback.c


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder 
-analyzer-config 
debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true
 %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+  char c;
+};
+
+void test() {
+  offsetof(struct S, c); 
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
\ No newline at end of file
Index: test/Analysis/Inputs/system-header-simulator.h
===
--- test/Analysis/Inputs/system-header-simulator.h
+++ test/Analysis/Inputs/system-header-simulator.h
@@ -110,4 +110,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
\ No newline at end of file
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,19 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNode *Node : PreVisit)
+VisitOffsetOfExpr(cast(S), Node, PostVisit);
+
+  getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
   Bldr.addNodes(Dst);
   break;
-
+}
 case Stmt::UnaryExprOrTypeTraitExprClass:
   Bldr.takeNodes(Pred);
   VisitUnaryExprOrTypeTraitExpr(cast(S),
Index: lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -33,6 +33,8 @@
  check::PostStmt,
  check::PreStmt,
  check::PostStmt,
+ check::PreStmt,
+ check::PostStmt,
  check::PreCall,
  check::PostCall,
  check::NewAllocator,
@@ -91,6 +93,16 @@
   llvm::errs() << "PostStmt\n";
   }
 
+  void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
+  llvm::errs() << "PreStmt\n";
+  }
+
+  void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
+  llvm::errs() << "PostStmt\n";
+  }
+
   void checkPreCall(const CallEvent , CheckerContext ) const {
 if (isCallbackEnabled(C, "PreCall")) {
   llvm::errs() << "PreCall";


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+  char c;
+};
+
+void test() {
+  offsetof(struct S, c); 
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
\ No newline at end of file
Index: test/Analysis/Inputs/system-header-simulator.h
===
--- test/Analysis/Inputs/system-header-simulator.h
+++ test/Analysis/Inputs/system-header-simulator.h
@@ -110,4 +110,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
\ No newline at end of file
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,19 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for 

[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-01-20 Thread Henry Wong via Phabricator via cfe-commits
MTC added a comment.

In https://reviews.llvm.org/D42300#982187, @NoQ wrote:

> My intuition suggests that this checker shouldn't be path-sensitive; our 
> path-sensitive analysis does very little to help you with this particular 
> checker, and you might end up with a much easier and more reliable checker if 
> you turn it into a simple AST visitor or an AST matcher. Just a heads up.


This is a very useful suggestion, many thanks, Noq! Path-sensitive is really a 
bit too heavy for this checker.


Repository:
  rC Clang

https://reviews.llvm.org/D42300



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-01-20 Thread Henry Wong via Phabricator via cfe-commits
MTC updated this revision to Diff 130753.
MTC added a comment.

- Use C++11 range-based for loop to traverse ExplodedNodeSet.
- Define the macro `offsetof` in `system-header-simulator.h`.


Repository:
  rC Clang

https://reviews.llvm.org/D42300

Files:
  lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/Analysis/Inputs/system-header-simulator.h
  test/Analysis/offsetofexpr-callback.c


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder 
-analyzer-config 
debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true
 %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+char c;
+};
+
+void test() {
+  offsetof(struct S, c);
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
Index: test/Analysis/Inputs/system-header-simulator.h
===
--- test/Analysis/Inputs/system-header-simulator.h
+++ test/Analysis/Inputs/system-header-simulator.h
@@ -109,4 +109,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,19 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNode *Node : PreVisit)
+VisitOffsetOfExpr(cast(S), Node, PostVisit);
+
+  getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
   Bldr.addNodes(Dst);
   break;
-
+}
 case Stmt::UnaryExprOrTypeTraitExprClass:
   Bldr.takeNodes(Pred);
   VisitUnaryExprOrTypeTraitExpr(cast(S),
Index: lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -33,6 +33,8 @@
  check::PostStmt,
  check::PreStmt,
  check::PostStmt,
+ check::PreStmt,
+ check::PostStmt,
  check::PreCall,
  check::PostCall,
  check::NewAllocator,
@@ -89,6 +91,16 @@
   llvm::errs() << "PostStmt\n";
   }
 
+  void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
+  llvm::errs() << "PreStmt\n";
+  }
+
+  void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
+  llvm::errs() << "PostStmt\n";
+  }
+
   void checkPreCall(const CallEvent , CheckerContext ) const {
 if (isCallbackEnabled(C, "PreCall")) {
   llvm::errs() << "PreCall";


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,13 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true %s 2>&1 | FileCheck %s
+#include "Inputs/system-header-simulator.h"
+
+struct S {
+char c;
+};
+
+void test() {
+  offsetof(struct S, c);
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
Index: test/Analysis/Inputs/system-header-simulator.h
===
--- test/Analysis/Inputs/system-header-simulator.h
+++ test/Analysis/Inputs/system-header-simulator.h
@@ -109,4 +109,6 @@
 #ifndef NULL
 #define __DARWIN_NULL 0
 #define NULL __DARWIN_NULL
-#endif
\ No newline at end of file
+#endif
+
+#define offsetof(t, d) __builtin_offsetof(t, d)
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,19 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNode *Node : PreVisit)
+

[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-01-19 Thread Artem Dergachev via Phabricator via cfe-commits
NoQ added a comment.

The patch seems correct, but i suspect that your overall approach to the 
checker you're trying to make is not ideal. `offsetof` returns a concrete value 
(because, well, symbolic `offsetof`s are not yet supported in the analyzer), 
and even if you see the concrete value, you'd be unable to track it, because 
when you get another concrete value with the same integer inside, you won't be 
able to easily figure out if its the same value or a different value. My 
intuition suggests that this checker shouldn't be path-sensitive; our 
path-sensitive analysis does very little to help you with this particular 
checker, and you might end up with a much easier and more reliable checker if 
you turn it into a simple AST visitor or an AST matcher. Just a heads up.


Repository:
  rC Clang

https://reviews.llvm.org/D42300



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-01-19 Thread Aleksei Sidorin via Phabricator via cfe-commits
a.sidorin added a comment.

Hello Henry,

The patch looks reasonable. I think it can be landed after comments are 
resolved.




Comment at: lib/StaticAnalyzer/Core/ExprEngine.cpp:1497
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNodeSet::iterator i = PreVisit.begin(), e = PreVisit.end();
+   i != e; ++i) {

Could you C++11-fy this loop?



Comment at: test/Analysis/offsetofexpr-callback.c:3
+
+#include 
+

Answering your question, we should put the declaration into 
system-header-simulator.h.



Comment at: test/Analysis/offsetofexpr-callback.c:7
+char c;
+double d;
+};

This decl seems unused. Should we remove it?


Repository:
  rC Clang

https://reviews.llvm.org/D42300



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D42300: [Analyzer] Add PreStmt and PostStmt callbacks for OffsetOfExpr

2018-01-19 Thread Henry Wong via Phabricator via cfe-commits
MTC created this revision.
MTC added reviewers: NoQ, a.sidorin, dcoughlin.
Herald added subscribers: cfe-commits, szepet, xazax.hun.

PreStmt and PostStmt callbacks for OffsetOfExpr are necessary to implement 
`Cert ARR39-C: Do not add or subtract a scaled integer to a pointer`. And 
should I define the `offsetof` macro in 
`clang/test/Analysis/Inputs/system-header-simulator.h`? Or, like 
`clang/test/Analysis/malloc-sizeof.c`, use `#include `?


Repository:
  rC Clang

https://reviews.llvm.org/D42300

Files:
  lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  test/Analysis/offsetofexpr-callback.c


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder 
-analyzer-config 
debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true
 %s 2>&1 | FileCheck %s
+
+#include 
+
+struct S {
+char c;
+double d;
+};
+
+void test() {
+  offsetof(struct S, c);
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,21 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNodeSet::iterator i = PreVisit.begin(), e = PreVisit.end();
+   i != e; ++i) {
+VisitOffsetOfExpr(cast(S), *i, PostVisit);
+  }
+
+  getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
   Bldr.addNodes(Dst);
   break;
-
+}
 case Stmt::UnaryExprOrTypeTraitExprClass:
   Bldr.takeNodes(Pred);
   VisitUnaryExprOrTypeTraitExpr(cast(S),
Index: lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++ lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
@@ -33,6 +33,8 @@
  check::PostStmt,
  check::PreStmt,
  check::PostStmt,
+ check::PreStmt,
+ check::PostStmt,
  check::PreCall,
  check::PostCall,
  check::NewAllocator,
@@ -89,6 +91,16 @@
   llvm::errs() << "PostStmt\n";
   }
 
+  void checkPreStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PreStmtOffsetOfExpr"))
+  llvm::errs() << "PreStmt\n";
+  }
+
+  void checkPostStmt(const OffsetOfExpr *OOE, CheckerContext ) const {
+if (isCallbackEnabled(C, "PostStmtOffsetOfExpr"))
+  llvm::errs() << "PostStmt\n";
+  }
+
   void checkPreCall(const CallEvent , CheckerContext ) const {
 if (isCallbackEnabled(C, "PreCall")) {
   llvm::errs() << "PreCall";


Index: test/Analysis/offsetofexpr-callback.c
===
--- /dev/null
+++ test/Analysis/offsetofexpr-callback.c
@@ -0,0 +1,15 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=debug.AnalysisOrder -analyzer-config debug.AnalysisOrder:PreStmtOffsetOfExpr=true,debug.AnalysisOrder:PostStmtOffsetOfExpr=true %s 2>&1 | FileCheck %s
+
+#include 
+
+struct S {
+char c;
+double d;
+};
+
+void test() {
+  offsetof(struct S, c);
+}
+
+// CHECK: PreStmt
+// CHECK-NEXT: PostStmt
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1488,12 +1488,21 @@
   Bldr.addNodes(Dst);
   break;
 
-case Stmt::OffsetOfExprClass:
+case Stmt::OffsetOfExprClass: {
   Bldr.takeNodes(Pred);
-  VisitOffsetOfExpr(cast(S), Pred, Dst);
+  ExplodedNodeSet PreVisit;
+  getCheckerManager().runCheckersForPreStmt(PreVisit, Pred, S, *this);
+
+  ExplodedNodeSet PostVisit;
+  for (ExplodedNodeSet::iterator i = PreVisit.begin(), e = PreVisit.end();
+   i != e; ++i) {
+VisitOffsetOfExpr(cast(S), *i, PostVisit);
+  }
+
+  getCheckerManager().runCheckersForPostStmt(Dst, PostVisit, S, *this);
   Bldr.addNodes(Dst);
   break;
-
+}
 case Stmt::UnaryExprOrTypeTraitExprClass:
   Bldr.takeNodes(Pred);
   VisitUnaryExprOrTypeTraitExpr(cast(S),
Index: lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
===
--- lib/StaticAnalyzer/Checkers/AnalysisOrderChecker.cpp
+++