diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index d9568b3eb1ab..3f287a0eb05a 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -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(Data); + } virtual bool isBoundable(ASTContext&) const { return false; } diff --git a/clang/include/clang/Analysis/PathSensitive/SVals.h b/clang/include/clang/Analysis/PathSensitive/SVals.h index 6c9285e53217..d16b3390ebee 100644 --- a/clang/include/clang/Analysis/PathSensitive/SVals.h +++ b/clang/include/clang/Analysis/PathSensitive/SVals.h @@ -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* diff --git a/clang/lib/Analysis/BasicObjCFoundationChecks.cpp b/clang/lib/Analysis/BasicObjCFoundationChecks.cpp index 88f480e68c07..0eee9374da36 100644 --- a/clang/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/clang/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -375,9 +375,9 @@ bool AuditCFNumberCreate::Audit(ExplodedNode* N,GRStateManager&){ CallExpr* CE = cast(cast(N->getLocation()).getStmt()); Expr* Callee = CE->getCallee(); SVal CallV = GetSVal(N->getState(), Callee); - loc::FuncVal* FuncV = dyn_cast(&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. diff --git a/clang/lib/Analysis/CFRefCount.cpp b/clang/lib/Analysis/CFRefCount.cpp index 7443c521b3bc..0e8d67ca292a 100644 --- a/clang/lib/Analysis/CFRefCount.cpp +++ b/clang/lib/Analysis/CFRefCount.cpp @@ -1694,7 +1694,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, Expr* Ex, Expr* Receiver, RetainSummary* Summ, - ExprIterator arg_beg, ExprIterator arg_end, + ExprIterator arg_beg, ExprIterator arg_end, ExplodedNode* Pred) { // Get the state. @@ -1930,9 +1930,9 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst, GRStmtNodeBuilder& Builder, CallExpr* CE, SVal L, ExplodedNode* Pred) { - - RetainSummary* Summ = !isa(L) ? 0 - : Summaries.getSummary(cast(L).getDecl()); + const FunctionDecl* FD = L.getAsFunctionDecl(); + RetainSummary* Summ = !FD ? 0 + : Summaries.getSummary(const_cast(FD)); EvalSummary(Dst, Eng, Builder, CE, 0, Summ, CE->arg_begin(), CE->arg_end(), Pred); @@ -2582,9 +2582,9 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode* N, if (CallExpr *CE = dyn_cast(S)) { // Get the name of the callee (if it is available). - SVal X = CurrSt.GetSValAsScalarOrLoc(CE->getCallee()); - if (loc::FuncVal* FV = dyn_cast(&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* N, if (contains(AEffects, MakeCollectable)) { // Get the name of the function. Stmt* S = cast(N->getLocation()).getStmt(); - loc::FuncVal FV = - cast(CurrSt.GetSValAsScalarOrLoc(cast(S)->getCallee())); - const std::string& FName = FV.getDecl()->getNameAsString(); + SVal X = CurrSt.GetSValAsScalarOrLoc(cast(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. diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 43d7331dd9ae..d00bfe640a01 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -976,7 +976,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst, } else if (const FunctionDecl* FD = dyn_cast(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& Dst, GRStmtNodeBuilder& Builder, CallExpr* CE, SVal L, ExplodedNode* Pred) { - - if (!isa(L)) + const FunctionDecl* FD = L.getAsFunctionDecl(); + if (!FD) return false; - - const FunctionDecl *FD = cast(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 OldSink(Builder->BuildSinks); - - if (isa(L)) { - - FunctionDecl* FD = cast(L).getDecl(); - + const FunctionDecl* FD = L.getAsFunctionDecl(); + if (FD) { if (FD->getAttr() || FD->getAttr()) Builder->BuildSinks = true; else { @@ -1559,10 +1555,9 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, // Evaluate the call. - if (isa(L)) { + if (FD) { - if (unsigned id - = cast(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. diff --git a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp index f4efdb1250f5..1b0314920418 100644 --- a/clang/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/clang/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -432,11 +432,11 @@ public: const GRState* state = N->getState(); SVal X = VMgr.GetSVal(state, CE->getCallee()); - - if (!isa(X)) + + const FunctionDecl* FD = X.getAsFunctionDecl(); + if (!FD) return false; - - FunctionDecl* FD = dyn_cast(cast(X).getDecl()); + const NonNullAttr* Att = FD->getAttr(); if (!Att) diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index 240280f68a74..875fd36747ce 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -30,9 +30,25 @@ using llvm::APSInt; // Utility methods. //===----------------------------------------------------------------------===// +const FunctionDecl* SVal::getAsFunctionDecl() const { + if (const loc::FuncVal* FV = dyn_cast(this)) { + return FV->getDecl(); + } + + if (const loc::MemRegionVal* X = dyn_cast(this)) { + const MemRegion* R = X->getRegion(); + if (const CodeTextRegion* CTR = dyn_cast(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(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(this)) return X->getSymbol();