[cfe-commits] r91710 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp test/Analysis/misc-ps-region-store.cpp

Ted Kremenek kremenek at apple.com
Fri Dec 18 12:13:40 PST 2009


Author: kremenek
Date: Fri Dec 18 14:13:39 2009
New Revision: 91710

URL: http://llvm.org/viewvc/llvm-project?rev=91710&view=rev
Log:
Enhance GRExprEngine::VisitCallExpr() to be used in an lvalue context.  Uncovered a new failing test case along the way, but we're making progress on handling C++ references in the analyzer.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=91710&r1=91709&r2=91710&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Fri Dec 18 14:13:39 2009
@@ -265,7 +265,7 @@
   /// VisitCall - Transfer function for function calls.
   void VisitCall(CallExpr* CE, ExplodedNode* Pred,
                  CallExpr::arg_iterator AI, CallExpr::arg_iterator AE,
-                 ExplodedNodeSet& Dst);
+                 ExplodedNodeSet& Dst, bool asLValue);
 
   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
   void VisitCast(Expr* CastE, Expr* Ex, ExplodedNode* Pred,

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=91710&r1=91709&r2=91710&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Dec 18 14:13:39 2009
@@ -46,6 +46,23 @@
   return Ctx.Selectors.getSelector(0, &II);
 }
 
+static bool CalleeReturnsReference(const CallExpr *CE) { 
+  const Expr *Callee = CE->getCallee();
+  QualType T = Callee->getType();
+  
+  
+  if (const PointerType *PT = T->getAs<PointerType>()) {
+    const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>();
+    T = FT->getResultType();
+  }
+  else {
+    const BlockPointerType *BT = T->getAs<BlockPointerType>();
+    T = BT->getPointeeType()->getAs<FunctionType>()->getResultType();
+  }
+  
+  return T->isReferenceType();
+}
+
 //===----------------------------------------------------------------------===//
 // Batch auditor.  DEPRECATED.
 //===----------------------------------------------------------------------===//
@@ -228,7 +245,7 @@
       CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
       CurrSet->clear();
     }
-    
+
     void *tag = I->first;
     Checker *checker = I->second;
     
@@ -593,7 +610,7 @@
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass: {
       CallExpr* C = cast<CallExpr>(S);
-      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
       break;
     }
 
@@ -745,6 +762,14 @@
       VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(Ex), Pred, Dst, true);
       return;
       
+    case Stmt::CallExprClass:
+    case Stmt::CXXOperatorCallExprClass: {
+      CallExpr* C = cast<CallExpr>(Ex);
+      assert(CalleeReturnsReference(C));
+      VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);      
+      break;
+    }
+      
     case Stmt::CompoundLiteralExprClass:
       VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true);
       return;      
@@ -1563,7 +1588,7 @@
 void GRExprEngine::VisitCall(CallExpr* CE, ExplodedNode* Pred,
                              CallExpr::arg_iterator AI,
                              CallExpr::arg_iterator AE,
-                             ExplodedNodeSet& Dst) {
+                             ExplodedNodeSet& Dst, bool asLValue) {
 
   // Determine the type of function we're calling (if available).
   const FunctionProtoType *Proto = NULL;
@@ -1577,7 +1602,7 @@
   WorkList.push_back(CallExprWLItem(AI, Pred));
   
   ExplodedNodeSet ArgsEvaluated;
-  
+
   while (!WorkList.empty()) {
     CallExprWLItem Item = WorkList.back();
     WorkList.pop_back();
@@ -1623,6 +1648,7 @@
   // Finally, evaluate the function call.  We try each of the checkers
   // to see if the can evaluate the function call.
   ExplodedNodeSet DstTmp3;
+
   
   for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
        DI != DE; ++DI) {
@@ -1664,7 +1690,28 @@
   
   // Finally, perform the post-condition check of the CallExpr and store
   // the created nodes in 'Dst'.
-  CheckerVisit(CE, Dst, DstTmp3, false);  
+  
+  if (!(!asLValue && CalleeReturnsReference(CE))) {
+    CheckerVisit(CE, Dst, DstTmp3, false);
+    return;
+  }
+  
+  // Handle the case where the called function returns a reference but
+  // we expect an rvalue.  For such cases, convert the reference to
+  // an rvalue.  
+  // FIXME: This conversion doesn't actually happen unless the result
+  //  of CallExpr is consumed by another expression.
+  ExplodedNodeSet DstTmp4;
+  CheckerVisit(CE, DstTmp4, DstTmp3, false);
+  QualType LoadTy = CE->getType();
+  
+  static int *ConvertToRvalueTag = 0;
+  for (ExplodedNodeSet::iterator NI = DstTmp4.begin(), NE = DstTmp4.end();
+       NI!=NE; ++NI) {
+    const GRState *state = GetState(*NI);
+    EvalLoad(Dst, CE, *NI, state, state->getSVal(CE),
+             &ConvertToRvalueTag, LoadTy);
+  }
 }
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.cpp?rev=91710&r1=91709&r2=91710&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.cpp (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.cpp Fri Dec 18 14:13:39 2009
@@ -2,8 +2,14 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin9 -analyze -analyzer-experimental-internal-checks -checker-cfref -analyzer-store=region -verify -fblocks   -analyzer-opt-analyze-nested-blocks %s
 // XFAIL: *
 
-// This test case currently crashes because of an assertion failure.
+// Test basic handling of references.
 char &test1_aux();
 char *test1() {
   return &test1_aux();
 }
+
+// This test currently crasehs because test1_aux() evaluates to a 'char' instead of a char& in CFRefCount.cpp.
+char test1_as_rvalue() {
+  return test1_aux();
+}
+





More information about the cfe-commits mailing list