aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h9
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h5
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp4
-rw-r--r--lib/Analysis/CFRefCount.cpp20
-rw-r--r--lib/Analysis/GRExprEngine.cpp21
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp8
-rw-r--r--lib/Analysis/SVals.cpp23
7 files changed, 57 insertions, 33 deletions
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index d9568b3eb1..3f287a0eb0 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/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<const FunctionDecl*>(Data);
+ }
virtual bool isBoundable(ASTContext&) const { return false; }
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index 6c9285e532..d16b3390eb 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/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/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 88f480e68c..0eee9374da 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -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.
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 7443c521b3..0e8d67ca29 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -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.
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 43d7331dd9..d00bfe640a 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -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.
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index f4efdb1250..1b03149204 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -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)
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index 240280f68a..875fd36747 100644
--- a/lib/Analysis/SVals.cpp
+++ b/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<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();