[cfe-commits] r129166 - in /cfe/trunk: lib/StaticAnalyzer/Core/CXXExprEngine.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/misc-ps-region-store.cpp
Ted Kremenek
kremenek at apple.com
Fri Apr 8 15:42:35 PDT 2011
Author: kremenek
Date: Fri Apr 8 17:42:35 2011
New Revision: 129166
URL: http://llvm.org/viewvc/llvm-project?rev=129166&view=rev
Log:
Start overhauling static analyzer support for C++ constructors. The inlining support isn't complete, and needs
to be reworked to model CallEnter/CallExit (just like all other calls). For now, treat constructors mostly
like other function calls, making the analysis of C++ code just a little more useful.
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
cfe/trunk/test/Analysis/misc-ps-region-store.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp?rev=129166&r1=129165&r2=129166&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CXXExprEngine.cpp Fri Apr 8 17:42:35 2011
@@ -124,53 +124,121 @@
}
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E,
- const MemRegion *Dest,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
- if (!Dest)
- Dest = svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
- Pred->getLocationContext());
-
- if (E->isElidable()) {
- VisitAggExpr(E->getArg(0), Dest, Pred, Dst);
- // FIXME: this is here to force propogation if VisitAggExpr doesn't
- if (Dst.empty())
- Dst.Add(Pred);
- return;
- }
+ const MemRegion *Dest,
+ ExplodedNode *Pred,
+ ExplodedNodeSet &destNodes) {
const CXXConstructorDecl *CD = E->getConstructor();
assert(CD);
-
+
+#if 0
if (!(CD->isThisDeclarationADefinition() && AMgr.shouldInlineCall()))
// FIXME: invalidate the object.
return;
-
+#endif
// Evaluate other arguments.
ExplodedNodeSet argsEvaluated;
const FunctionProtoType *FnType = CD->getType()->getAs<FunctionProtoType>();
evalArguments(E->arg_begin(), E->arg_end(), FnType, Pred, argsEvaluated);
- // The callee stack frame context used to create the 'this' parameter region.
- const StackFrameContext *SFC = AMgr.getStackFrame(CD,
- Pred->getLocationContext(),
- E, Builder->getBlock(),
- Builder->getIndex());
- const CXXThisRegion *ThisR =getCXXThisRegion(E->getConstructor()->getParent(),
- SFC);
+#if 0
+ // Is the constructor elidable?
+ if (E->isElidable()) {
+ VisitAggExpr(E->getArg(0), destNodes, Pred, Dst);
+ // FIXME: this is here to force propogation if VisitAggExpr doesn't
+ if (destNodes.empty())
+ destNodes.Add(Pred);
+ return;
+ }
+#endif
+
+ // Perform the previsit of the constructor.
+ ExplodedNodeSet destPreVisit;
+ getCheckerManager().runCheckersForPreStmt(destPreVisit, argsEvaluated, E,
+ *this);
+
+ // Evaluate the constructor. Currently we don't now allow checker-specific
+ // implementations of specific constructors (as we do with ordinary
+ // function calls. We can re-evaluate this in the future.
+
+#if 0
+ // Inlining currently isn't fully implemented.
+
+ if (AMgr.shouldInlineCall()) {
+ if (!Dest)
+ Dest =
+ svalBuilder.getRegionManager().getCXXTempObjectRegion(E,
+ Pred->getLocationContext());
+
+ // The callee stack frame context used to create the 'this'
+ // parameter region.
+ const StackFrameContext *SFC =
+ AMgr.getStackFrame(CD, Pred->getLocationContext(),
+ E, Builder->getBlock(), Builder->getIndex());
+
+ // Create the 'this' region.
+ const CXXThisRegion *ThisR =
+ getCXXThisRegion(E->getConstructor()->getParent(), SFC);
+
+ CallEnter Loc(E, SFC, Pred->getLocationContext());
+
+
+ for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
+ NE = argsEvaluated.end(); NI != NE; ++NI) {
+ const GRState *state = GetState(*NI);
+ // Setup 'this' region, so that the ctor is evaluated on the object pointed
+ // by 'Dest'.
+ state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
+ if (ExplodedNode *N = Builder->generateNode(Loc, state, *NI))
+ destNodes.Add(N);
+ }
+ }
+#endif
+
+ // Default semantics: invalidate all regions passed as arguments.
+ llvm::SmallVector<const MemRegion*, 10> regionsToInvalidate;
+
+ // FIXME: We can have collisions on the conjured symbol if the
+ // expression *I also creates conjured symbols. We probably want
+ // to identify conjured symbols by an expression pair: the enclosing
+ // expression (the context) and the expression itself. This should
+ // disambiguate conjured symbols.
+ unsigned blockCount = Builder->getCurrentBlockCount();
+
+ // NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
+ // global variables.
+ ExplodedNodeSet destCall;
+
+ for (ExplodedNodeSet::iterator
+ i = destPreVisit.begin(), e = destPreVisit.end();
+ i != e; ++i)
+ {
+ ExplodedNode *Pred = *i;
+ const GRState *state = GetState(Pred);
- CallEnter Loc(E, SFC, Pred->getLocationContext());
- for (ExplodedNodeSet::iterator NI = argsEvaluated.begin(),
- NE = argsEvaluated.end(); NI != NE; ++NI) {
- const GRState *state = GetState(*NI);
- // Setup 'this' region, so that the ctor is evaluated on the object pointed
- // by 'Dest'.
- state = state->bindLoc(loc::MemRegionVal(ThisR), loc::MemRegionVal(Dest));
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- if (N)
- Dst.Add(N);
+ // Accumulate list of regions that are invalidated.
+ for (CXXConstructExpr::const_arg_iterator
+ ai = E->arg_begin(), ae = E->arg_end();
+ ai != ae; ++ai)
+ {
+ SVal val = state->getSVal(*ai);
+ if (const MemRegion *region = val.getAsRegion())
+ regionsToInvalidate.push_back(region);
+ }
+
+ // Invalidate the regions.
+ state = state->invalidateRegions(regionsToInvalidate.data(),
+ regionsToInvalidate.data() +
+ regionsToInvalidate.size(),
+ E, blockCount, 0,
+ /* invalidateGlobals = */ true);
+
+ Builder->MakeNode(destCall, E, Pred, state);
}
+
+ // Do the post visit.
+ getCheckerManager().runCheckersForPostStmt(destNodes, destCall, E, *this);
}
void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=129166&r1=129165&r2=129166&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Apr 8 17:42:35 2011
@@ -422,7 +422,6 @@
// C++ stuff we don't support yet.
case Stmt::CXXBindTemporaryExprClass:
case Stmt::CXXCatchStmtClass:
- case Stmt::CXXDefaultArgExprClass:
case Stmt::CXXDependentScopeMemberExprClass:
case Stmt::CXXNullPtrLiteralExprClass:
case Stmt::CXXPseudoDestructorExprClass:
@@ -448,7 +447,14 @@
Engine.addAbortedBlock(node, Builder->getBlock());
break;
}
-
+
+ // We don't handle default arguments either yet, but we can fake it
+ // for now by just skipping them.
+ case Stmt::CXXDefaultArgExprClass: {
+ Dst.Add(Pred);
+ break;
+ }
+
case Stmt::ParenExprClass:
llvm_unreachable("ParenExprs already handled.");
// Cases that should never be evaluated simply because they shouldn't
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=129166&r1=129165&r2=129166&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.cpp (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.cpp Fri Apr 8 17:42:35 2011
@@ -278,3 +278,28 @@
return val;
}
+// Test constructors invalidating arguments. Previously this raised
+// an uninitialized value warning.
+extern "C" void __attribute__((noreturn)) PR9645_exit(int i);
+
+class PR9645_SideEffect
+{
+public:
+ PR9645_SideEffect(int *pi); // caches pi in i_
+ void Read(int *pi); // copies *pi into *i_
+private:
+ int *i_;
+};
+
+void PR9645() {
+ int i;
+
+ PR9645_SideEffect se(&i);
+ int j = 1;
+ se.Read(&j); // this has a side-effect of initializing i.
+
+ PR9645_exit(i); // no-warning
+}
+
+PR9645_SideEffect::PR9645_SideEffect(int *pi) : i_(pi) {}
+void PR9645_SideEffect::Read(int *pi) { *i_ = *pi; }
More information about the cfe-commits
mailing list