]> granicus.if.org Git - clang/commitdiff
get a CodeTextRegion when visiting FunctionDecl reference.
authorZhongxing Xu <xuzhongxing@gmail.com>
Mon, 20 Apr 2009 05:24:46 +0000 (05:24 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Mon, 20 Apr 2009 05:24:46 +0000 (05:24 +0000)
get FunctionDecl with more general utility method.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69570 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/MemRegion.h
include/clang/Analysis/PathSensitive/SVals.h
lib/Analysis/BasicObjCFoundationChecks.cpp
lib/Analysis/CFRefCount.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRExprEngineInternalChecks.cpp
lib/Analysis/SVals.cpp

index d9568b3eb1aba9ca314e058ea4095c31b849c3ef..3f287a0eb05a0e84b0104f4b7ccbfb410c45caf7 100644 (file)
@@ -39,11 +39,11 @@ class MemRegionManager;
 class MemRegion : public llvm::FoldingSetNode {
 public:
   enum Kind { MemSpaceRegionKind,
-              CodeTextRegionKind,
               SymbolicRegionKind,
               AllocaRegionKind,
               // Typed regions.
               BEG_TYPED_REGIONS,
+               CodeTextRegionKind,
                CompoundLiteralRegionKind,
                StringRegionKind, ElementRegionKind,
                TypedViewRegionKind,
@@ -215,6 +215,13 @@ public:
   QualType getLValueType(ASTContext &C) const {
     return LocationType;
   }
+
+  bool isDeclared() const { return codekind == Declared; }
+
+  const FunctionDecl* getDecl() const {
+    assert(codekind == Declared);
+    return static_cast<const FunctionDecl*>(Data);
+  }
   
   virtual bool isBoundable(ASTContext&) const { return false; }
 
index 6c9285e53217d09a9d9482c4d85dc7b89b911cb5..d16b3390ebeec47386a667dfa1632b1f488aebc1 100644 (file)
@@ -89,6 +89,11 @@ public:
   }
   
   bool isZeroConstant() const;
+
+  /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
+  /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl. 
+  /// Otherwise return 0.
+  const FunctionDecl* getAsFunctionDecl() const;
   
   /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and 
   ///  wraps a symbol, return that SymbolRef.  Otherwise return a SymbolData*
index 88f480e68c07992cac52ed7f0c91bd3c3993326f..0eee9374da362121724532885f80ba36e16ae908 100644 (file)
@@ -375,9 +375,9 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
   CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
   Expr* Callee = CE->getCallee();  
   SVal CallV = GetSVal(N->getState(), Callee);  
-  loc::FuncVal* FuncV = dyn_cast<loc::FuncVal>(&CallV);
+  const FunctionDecl* FD = CallV.getAsFunctionDecl();
 
-  if (!FuncV || FuncV->getDecl()->getIdentifier() != II || CE->getNumArgs()!=3)
+  if (!FD || FD->getIdentifier() != II || CE->getNumArgs()!=3)
     return false;
   
   // Get the value of the "theType" argument.
index 7443c521b3bc4794cb62108bdba38539550e6a03..0e8d67ca292aca8d6b74705e14dc949984975bc8 100644 (file)
@@ -1694,7 +1694,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
                              Expr* Ex,
                              Expr* Receiver,
                              RetainSummary* Summ,
-                             ExprIterator arg_beg, ExprIterator arg_end,                             
+                             ExprIterator arg_beg, ExprIterator arg_end,
                              ExplodedNode<GRState>* Pred) {
   
   // Get the state.
@@ -1930,9 +1930,9 @@ void CFRefCount::EvalCall(ExplodedNodeSet<GRState>& Dst,
                           GRStmtNodeBuilder<GRState>& Builder,
                           CallExpr* CE, SVal L,
                           ExplodedNode<GRState>* Pred) {
-
-  RetainSummary* Summ = !isa<loc::FuncVal>(L) ? 0
-                      : Summaries.getSummary(cast<loc::FuncVal>(L).getDecl());
+  const FunctionDecl* FD = L.getAsFunctionDecl();
+  RetainSummary* Summ = !FD ? 0 
+                        : Summaries.getSummary(const_cast<FunctionDecl*>(FD));
   
   EvalSummary(Dst, Eng, Builder, CE, 0, Summ,
               CE->arg_begin(), CE->arg_end(), Pred);
@@ -2582,9 +2582,9 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
 
     if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
       // Get the name of the callee (if it is available).
-      SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee());        
-      if (loc::FuncVal* FV = dyn_cast<loc::FuncVal>(&X))
-        os << "Call to function '" << FV->getDecl()->getNameAsString() <<'\'';
+      SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee());
+      if (const FunctionDecl* FD = X.getAsFunctionDecl())
+        os << "Call to function '" << FD->getNameAsString() <<'\'';
       else
         os << "function call";      
     }          
@@ -2675,9 +2675,9 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
     if (contains(AEffects, MakeCollectable)) {
       // Get the name of the function.
       Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
-      loc::FuncVal FV =
-        cast<loc::FuncVal>(CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee()));
-      const std::string& FName = FV.getDecl()->getNameAsString();
+      SVal X = CurrSt.GetSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee());
+      const FunctionDecl* FD = X.getAsFunctionDecl();
+      const std::string& FName = FD->getNameAsString();
       
       if (TF.isGCEnabled()) {
         // Determine if the object's reference count was pushed to zero.
index 43d7331dd9ae6018982b215064524ac2260eee07..d00bfe640a0169afb9b11544508425c981d025cf 100644 (file)
@@ -976,7 +976,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
 
   } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
     assert(asLValue);
-    SVal V = loc::FuncVal(FD);
+    SVal V = ValMgr.getFunctionPointer(FD);
     MakeNode(Dst, Ex, Pred, BindExpr(state, Ex, V));
     return;
   }
@@ -1369,11 +1369,10 @@ static bool EvalOSAtomic(ExplodedNodeSet<GRState>& Dst,
                          GRStmtNodeBuilder<GRState>& Builder,
                          CallExpr* CE, SVal L,
                          ExplodedNode<GRState>* Pred) {
-  
-  if (!isa<loc::FuncVal>(L))
+  const FunctionDecl* FD = L.getAsFunctionDecl();
+  if (!FD)
     return false;
-  
-  const FunctionDecl *FD = cast<loc::FuncVal>(L).getDecl();
+
   const char *FName = FD->getNameAsCString();
   
   // Check for compare and swap.
@@ -1473,11 +1472,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
     // Check for the "noreturn" attribute.
     
     SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    
-    if (isa<loc::FuncVal>(L)) {      
-      
-      FunctionDecl* FD = cast<loc::FuncVal>(L).getDecl();
-      
+    const FunctionDecl* FD = L.getAsFunctionDecl();
+    if (FD) {      
       if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>())
         Builder->BuildSinks = true;
       else {
@@ -1559,10 +1555,9 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred,
     
     // Evaluate the call.
 
-    if (isa<loc::FuncVal>(L)) {
+    if (FD) {
       
-      if (unsigned id 
-            = cast<loc::FuncVal>(L).getDecl()->getBuiltinID(getContext()))
+      if (unsigned id = FD->getBuiltinID(getContext()))
         switch (id) {
           case Builtin::BI__builtin_expect: {
             // For __builtin_expect, just return the value of the subexpression.
index f4efdb1250f59b3c5a57857cea27908a7ba34860..1b03149204188e13ee8ad5c3627c890b1d9daf1b 100644 (file)
@@ -432,11 +432,11 @@ public:
     const GRState* state = N->getState();
     
     SVal X = VMgr.GetSVal(state, CE->getCallee());
-    
-    if (!isa<loc::FuncVal>(X))
+
+    const FunctionDecl* FD = X.getAsFunctionDecl();
+    if (!FD)
       return false;
-    
-    FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
+
     const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
     
     if (!Att)
index 240280f68a744d053c960050ca103a2f7ca9130f..875fd36747cece8981a2d3c68f99c58951d56220 100644 (file)
@@ -30,9 +30,25 @@ using llvm::APSInt;
 // Utility methods.
 //===----------------------------------------------------------------------===//
 
+const FunctionDecl* SVal::getAsFunctionDecl() const {
+  if (const loc::FuncVal* FV = dyn_cast<loc::FuncVal>(this)) {
+    return FV->getDecl();
+  }
+
+  if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
+    const MemRegion* R = X->getRegion();
+    if (const CodeTextRegion* CTR = dyn_cast<CodeTextRegion>(R)) {
+      if (CTR->isDeclared())
+        return CTR->getDecl();
+    }
+  }
+
+  return 0;
+}
+
 /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and 
-///  wraps a symbol, return that SymbolRef.  Otherwise return a SymbolRef
-///  where 'isValid()' returns false.
+///  wraps a symbol, return that SymbolRef.  Otherwise return 0.
+// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
 SymbolRef SVal::getAsLocSymbol() const {
   if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
     const MemRegion *R = X->getRegion();
@@ -55,7 +71,8 @@ SymbolRef SVal::getAsLocSymbol() const {
 }
 
 /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
-///  Otherwise return a SymbolRef where 'isValid()' returns false.
+///  Otherwise return 0.
+// FIXME: should we consider SymbolRef wrapped in CodeTextRegion?
 SymbolRef SVal::getAsSymbol() const {
   if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
     return X->getSymbol();