Turn -analyzer-inline-call on for C functions. This also fixed a bug that
after inlining post-call checking shouldn't be done.

llvm-svn: 103161
diff --git a/clang/include/clang/Checker/PathSensitive/GRExprEngine.h b/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
index f04ca75..ac407f6 100644
--- a/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
+++ b/clang/include/clang/Checker/PathSensitive/GRExprEngine.h
@@ -456,6 +456,8 @@
   void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred,
                     const GRState* St, SVal location,
                     const void *tag, bool isLoad);
+
+  bool InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, ExplodedNode *Pred);
 };
 
 } // end clang namespace
diff --git a/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp
index 67090b8..b7b48d7 100644
--- a/clang/lib/Checker/GRExprEngine.cpp
+++ b/clang/lib/Checker/GRExprEngine.cpp
@@ -1810,6 +1810,28 @@
   }
 }
 
+bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE, 
+                              ExplodedNode *Pred) {
+  const GRState *state = GetState(Pred);
+  const Expr *Callee = CE->getCallee();
+  SVal L = state->getSVal(Callee);
+  
+  const FunctionDecl *FD = L.getAsFunctionDecl();
+  if (!FD)
+    return false;
+
+  if (!FD->getBody(FD))
+    return false;
+
+  // Now we have the definition of the callee, create a CallEnter node.
+  CallEnter Loc(CE, FD, Pred->getLocationContext());
+
+  ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
+  if (N)
+    Dst.Add(N);
+  return true;
+}
+
 void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
                              CallExpr::arg_iterator AI,
                              CallExpr::arg_iterator AE,
@@ -1889,6 +1911,10 @@
     // If the callee is processed by a checker, skip the rest logic.
     if (CheckerEvalCall(CE, DstChecker, *DI))
       DstTmp3.insert(DstChecker);
+    else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {
+      // Callee is inlined. We shouldn't do post call checking.
+      return;
+    }
     else {
       for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
            DE_Checker = DstChecker.end();
diff --git a/clang/test/Analysis/inline.c b/clang/test/Analysis/inline.c
index acaf74d..50c1a54 100644
--- a/clang/test/Analysis/inline.c
+++ b/clang/test/Analysis/inline.c
@@ -1,5 +1,5 @@
-// RUN: false
-// XFAIL: *
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
+
 int f1() {
   int y = 1;
   y++;
diff --git a/clang/test/Analysis/inline2.c b/clang/test/Analysis/inline2.c
index ec965a6..efdb75c 100644
--- a/clang/test/Analysis/inline2.c
+++ b/clang/test/Analysis/inline2.c
@@ -1,5 +1,4 @@
-// RUN: false
-// XFAIL: *
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
 
 // Test parameter 'a' is registered to LiveVariables analysis data although it
 // is not referenced in the function body. 
diff --git a/clang/test/Analysis/inline3.c b/clang/test/Analysis/inline3.c
index 8f45858..884b3ed 100644
--- a/clang/test/Analysis/inline3.c
+++ b/clang/test/Analysis/inline3.c
@@ -1,5 +1,4 @@
-// RUN: false
-// XFAIL: *
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
 
 // Test when entering f1(), we set the right AnalysisContext to Environment.
 // Otherwise, block-level expr '1 && a' would not be block-level.
diff --git a/clang/test/Analysis/inline4.c b/clang/test/Analysis/inline4.c
index b2b3c34..5a1d193 100644
--- a/clang/test/Analysis/inline4.c
+++ b/clang/test/Analysis/inline4.c
@@ -1,5 +1,5 @@
-// RUN: false
-// XFAIL: *
+// RUN: %clang_cc1 -analyze -analyzer-check-objc-mem -analyzer-inline-call -analyzer-store region -verify %s
+
 int g(int a) {    
   return a;
 }