Add ObjCAtSynchronizedStmt to the CFG and add GRExprEngine support (PreVisit for checkers).

llvm-svn: 113572
diff --git a/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def b/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def
index 2edc4a3..e68c148 100644
--- a/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def
+++ b/clang/include/clang/Checker/PathSensitive/CheckerVisitor.def
@@ -24,6 +24,7 @@
 PREVISIT(CallExpr, Stmt)
 PREVISIT(CXXOperatorCallExpr, CallExpr)
 PREVISIT(DeclStmt, Stmt)
+PREVISIT(ObjCAtSynchronizedStmt, Stmt)
 PREVISIT(ObjCMessageExpr, Stmt)
 PREVISIT(ReturnStmt, Stmt)
 
diff --git a/clang/include/clang/Checker/PathSensitive/GRExprEngine.h b/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
index b8ccc06..39c3ea5 100644
--- a/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -26,6 +26,7 @@
 #include "clang/AST/Type.h"
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtObjC.h"
 
 namespace clang {
 class AnalysisManager;
@@ -386,6 +387,10 @@
   void VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred, 
                        ExplodedNodeSet& Dst, bool asLValue);
 
+  /// Transfer function logic for ObjCAtSynchronizedStmts.
+  void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+                                   ExplodedNode *Pred, ExplodedNodeSet &Dst);
+
   /// VisitObjCIvarRefExpr - Transfer function logic for ObjCIvarRefExprs.
   void VisitObjCIvarRefExpr(const ObjCIvarRefExpr* DR, ExplodedNode* Pred,
                             ExplodedNodeSet& Dst, bool asLValue);
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 5977de6..8044760 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -1244,6 +1244,10 @@
     Succ = SyncBlock;
   }
 
+  // Add the @synchronized to the CFG.
+  autoCreateBlock();
+  AppendStmt(Block, S, AddStmtChoice::AlwaysAdd);
+
   // Inline the sync expression.
   return addStmt(S->getSynchExpr());
 }
diff --git a/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp
index 18124e4..851f34e 100644
--- a/clang/lib/Checker/GRExprEngine.cpp
+++ b/clang/lib/Checker/GRExprEngine.cpp
@@ -809,6 +809,10 @@
       break;
     }
 
+    case Stmt::ObjCAtSynchronizedStmtClass:
+      VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S), Pred, Dst);
+      break;
+
     // Cases not handled yet; but will handle some day.
     case Stmt::DesignatedInitExprClass:
     case Stmt::ExtVectorElementExprClass:
@@ -816,7 +820,6 @@
     case Stmt::ImplicitValueInitExprClass:
     case Stmt::ObjCAtCatchStmtClass:
     case Stmt::ObjCAtFinallyStmtClass:
-    case Stmt::ObjCAtSynchronizedStmtClass:
     case Stmt::ObjCAtTryStmtClass:
     case Stmt::ObjCEncodeExprClass:
     case Stmt::ObjCImplicitSetterGetterRefExprClass:
@@ -2244,6 +2247,23 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Transfer function: Objective-C @synchronized.
+//===----------------------------------------------------------------------===//
+
+void GRExprEngine::VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
+                                               ExplodedNode *Pred,
+                                               ExplodedNodeSet &Dst) {
+
+  // The mutex expression is a CFGElement, so we don't need to explicitly
+  // visit it since it will already be processed.
+
+  // Pre-visit the ObjCAtSynchronizedStmt.
+  ExplodedNodeSet Tmp;
+  Tmp.Add(Pred);
+  CheckerVisit(S, Dst, Tmp, PreVisitStmtCallback);
+}
+
+//===----------------------------------------------------------------------===//
 // Transfer function: Objective-C ivar references.
 //===----------------------------------------------------------------------===//