static analyzer: refactor checking logic for returning the address of a stack variable or a garbage
value into their own respective subclasses of Checker (and put them in .cpp files where their
implementation details are hidden from GRExprEngine).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@86215 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 212fea3..1bfb49d 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -2628,63 +2628,37 @@
VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
}
-void GRExprEngine::EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* S,
- ExplodedNode* Pred) {
- assert (Builder && "GRStmtNodeBuilder must be defined.");
-
- unsigned size = Dst.size();
-
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- getTF().EvalReturn(Dst, *this, *Builder, S, Pred);
-
- // Handle the case where no nodes where generated.
-
- if (!Builder->BuildSinks && Dst.size() == size && !Builder->HasGeneratedNode)
- MakeNode(Dst, S, Pred, GetState(Pred));
-}
-
-void GRExprEngine::VisitReturnStmt(ReturnStmt* S, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
-
- Expr* R = S->getRetValue();
-
- if (!R) {
- EvalReturn(Dst, S, Pred);
- return;
+void GRExprEngine::VisitReturnStmt(ReturnStmt *RS, ExplodedNode *Pred,
+ ExplodedNodeSet &Dst) {
+
+ ExplodedNodeSet Src;
+ if (Expr *RetE = RS->getRetValue()) {
+ Visit(RetE, Pred, Src);
}
+ else {
+ Src.Add(Pred);
+ }
+
+ ExplodedNodeSet CheckedSet;
+ CheckerVisit(RS, CheckedSet, Src, true);
+
+ for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
+ I != E; ++I) {
- ExplodedNodeSet Tmp;
- Visit(R, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- SVal X = (*I)->getState()->getSVal(R);
-
- // Check if we return the address of a stack variable.
- if (isa<loc::MemRegionVal>(X)) {
- // Determine if the value is on the stack.
- const MemRegion* R = cast<loc::MemRegionVal>(&X)->getRegion();
-
- if (R && R->hasStackStorage()) {
- // Create a special node representing the error.
- if (ExplodedNode* N = Builder->generateNode(S, GetState(*I), *I)) {
- N->markAsSink();
- RetsStackAddr.insert(N);
- }
- continue;
- }
- }
- // Check if we return an undefined value.
- else if (X.isUndef()) {
- if (ExplodedNode* N = Builder->generateNode(S, GetState(*I), *I)) {
- N->markAsSink();
- RetsUndef.insert(N);
- }
- continue;
- }
-
- EvalReturn(Dst, S, *I);
+ assert(Builder && "GRStmtNodeBuilder must be defined.");
+
+ Pred = *I;
+ unsigned size = Dst.size();
+
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+ SaveOr OldHasGen(Builder->HasGeneratedNode);
+
+ getTF().EvalReturn(Dst, *this, *Builder, RS, Pred);
+
+ // Handle the case where no nodes where generated.
+ if (!Builder->BuildSinks && Dst.size() == size &&
+ !Builder->HasGeneratedNode)
+ MakeNode(Dst, RS, Pred, GetState(Pred));
}
}