[cfe-commits] r49752 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/GRTransferFuncs.h lib/Analysis/GRExprEngine.cpp lib/Analysis/GRSimpleVals.cpp lib/Analysis/GRSimpleVals.h
Ted Kremenek
kremenek at apple.com
Tue Apr 15 16:06:53 PDT 2008
Author: kremenek
Date: Tue Apr 15 18:06:53 2008
New Revision: 49752
URL: http://llvm.org/viewvc/llvm-project?rev=49752&view=rev
Log:
Added some comments to GRExprEngine. Reorder some of the method definitions
to start logically organizing them.
Added initial plug-in transfer function support for Objective-C message expressions.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/GRSimpleVals.cpp
cfe/trunk/lib/Analysis/GRSimpleVals.h
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=49752&r1=49751&r2=49752&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Apr 15 18:06:53 2008
@@ -594,7 +594,12 @@
void EvalCall(NodeSet& Dst, CallExpr* CE, LVal L, NodeTy* Pred) {
assert (Builder && "GRStmtNodeBuilder must be defined.");
- return TF->EvalCall(Dst, *this, *Builder, CE, L, Pred);
+ TF->EvalCall(Dst, *this, *Builder, CE, L, Pred);
+ }
+
+ void EvalObjCMessageExpr(NodeSet& Dst, ObjCMessageExpr* ME, NodeTy* Pred) {
+ assert (Builder && "GRStmtNodeBuilder must be defined.");
+ TF->EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred);
}
ValueState* MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken);
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h?rev=49752&r1=49751&r2=49752&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRTransferFuncs.h Tue Apr 15 18:06:53 2008
@@ -66,6 +66,12 @@
CallExpr* CE, LVal L,
ExplodedNode<ValueState>* Pred) = 0;
+ virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<ValueState>& Builder,
+ ObjCMessageExpr* ME,
+ ExplodedNode<ValueState>* Pred) = 0;
+
// End-of-path.
virtual void EvalEndPath(GRExprEngine& Engine,
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=49752&r1=49751&r2=49752&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Apr 15 18:06:53 2008
@@ -23,23 +23,15 @@
#include <sstream>
#endif
-// SaveAndRestore - A utility class that uses RIIA to save and restore
-// the value of a variable.
-template<typename T>
-struct VISIBILITY_HIDDEN SaveAndRestore {
- SaveAndRestore(T& x) : X(x), old_value(x) {}
- ~SaveAndRestore() { X = old_value; }
- T get() { return old_value; }
-
- T& X;
- T old_value;
-};
-
using namespace clang;
using llvm::dyn_cast;
using llvm::cast;
using llvm::APSInt;
+//===----------------------------------------------------------------------===//
+// Engine construction and deletion.
+//===----------------------------------------------------------------------===//
+
GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx)
: CoreEngine(cfg, CD, Ctx, *this),
@@ -70,6 +62,22 @@
delete *I;
}
+//===----------------------------------------------------------------------===//
+// Utility methods.
+//===----------------------------------------------------------------------===//
+
+// SaveAndRestore - A utility class that uses RIIA to save and restore
+// the value of a variable.
+template<typename T>
+struct VISIBILITY_HIDDEN SaveAndRestore {
+ SaveAndRestore(T& x) : X(x), old_value(x) {}
+ ~SaveAndRestore() { X = old_value; }
+ T get() { return old_value; }
+
+ T& X;
+ T old_value;
+};
+
void GRExprEngine::EmitWarnings(Diagnostic& Diag, PathDiagnosticClient* PD) {
for (bug_type_iterator I = bug_types_begin(), E = bug_types_end(); I!=E; ++I){
BugReporter BR(Diag, PD, getContext(), *this);
@@ -140,6 +148,208 @@
return StateMgr.SetRVal(St, Ex, V, isBlkExpr, false);
}
+//===----------------------------------------------------------------------===//
+// Top-level transfer function logic (Dispatcher).
+//===----------------------------------------------------------------------===//
+
+void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
+
+ Builder = &builder;
+ StmtEntryNode = builder.getLastNode();
+ CurrentStmt = S;
+ NodeSet Dst;
+
+ // Set up our simple checks.
+
+ // FIXME: This can probably be installed directly in GRCoreEngine, obviating
+ // the need to do a copy every time we hit a block-level statement.
+
+ if (!MsgExprChecks.empty())
+ Builder->setObjCMsgExprAuditors((GRAuditor<ValueState>**) &MsgExprChecks[0],
+ (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size()));
+
+
+ if (!CallChecks.empty())
+ Builder->setCallExprAuditors((GRAuditor<ValueState>**) &CallChecks[0],
+ (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size()));
+
+ // Create the cleaned state.
+
+ CleanedState = StateMgr.RemoveDeadBindings(StmtEntryNode->getState(),
+ CurrentStmt, Liveness);
+
+ Builder->SetCleanedState(CleanedState);
+
+ // Visit the statement.
+
+ Visit(S, StmtEntryNode, Dst);
+
+ // If no nodes were generated, generate a new node that has all the
+ // dead mappings removed.
+
+ if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode)
+ builder.generateNode(S, GetState(StmtEntryNode), StmtEntryNode);
+
+ // NULL out these variables to cleanup.
+
+ CurrentStmt = NULL;
+ StmtEntryNode = NULL;
+ Builder = NULL;
+ CleanedState = NULL;
+}
+
+void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
+
+ // FIXME: add metadata to the CFG so that we can disable
+ // this check when we KNOW that there is no block-level subexpression.
+ // The motivation is that this check requires a hashtable lookup.
+
+ if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
+ Dst.Add(Pred);
+ return;
+ }
+
+ switch (S->getStmtClass()) {
+
+ default:
+ // Cases we intentionally have "default" handle:
+ // AddrLabelExpr, IntegerLiteral, CharacterLiteral
+
+ Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
+ break;
+
+ case Stmt::AsmStmtClass:
+ VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperator* B = cast<BinaryOperator>(S);
+
+ if (B->isLogicalOp()) {
+ VisitLogicalExpr(B, Pred, Dst);
+ break;
+ }
+ else if (B->getOpcode() == BinaryOperator::Comma) {
+ ValueState* St = GetState(Pred);
+ MakeNode(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS())));
+ break;
+ }
+
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CallExprClass: {
+ CallExpr* C = cast<CallExpr>(S);
+ VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
+ break;
+ }
+
+ case Stmt::CastExprClass: {
+ CastExpr* C = cast<CastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
+ // FIXME: ChooseExpr is really a constant. We need to fix
+ // the CFG do not model them as explicit control-flow.
+
+ case Stmt::ChooseExprClass: { // __builtin_choose_expr
+ ChooseExpr* C = cast<ChooseExpr>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::CompoundAssignOperatorClass:
+ VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
+ break;
+
+ case Stmt::ConditionalOperatorClass: { // '?' operator
+ ConditionalOperator* C = cast<ConditionalOperator>(S);
+ VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::DeclRefExprClass:
+ VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::DeclStmtClass:
+ VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
+ break;
+
+ case Stmt::ImplicitCastExprClass: {
+ ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
+ VisitCast(C, C->getSubExpr(), Pred, Dst);
+ break;
+ }
+
+ case Stmt::ObjCMessageExprClass: {
+ VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
+ break;
+ }
+
+ case Stmt::ParenExprClass:
+ Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
+ break;
+
+ case Stmt::SizeOfAlignOfTypeExprClass:
+ VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
+ break;
+
+ case Stmt::StmtExprClass: {
+ StmtExpr* SE = cast<StmtExpr>(S);
+
+ ValueState* St = GetState(Pred);
+
+ // FIXME: Not certain if we can have empty StmtExprs. If so, we should
+ // probably just remove these from the CFG.
+ assert (!SE->getSubStmt()->body_empty());
+
+ if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin()))
+ MakeNode(Dst, SE, Pred, SetRVal(St, SE, GetRVal(St, LastExpr)));
+ else
+ Dst.Add(Pred);
+
+ break;
+ }
+
+ // FIXME: We may wish to always bind state to ReturnStmts so
+ // that users can quickly query what was the state at the
+ // exit points of a function.
+
+ case Stmt::ReturnStmtClass:
+ VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); break;
+
+ case Stmt::UnaryOperatorClass: {
+ UnaryOperator* U = cast<UnaryOperator>(S);
+
+ switch (U->getOpcode()) {
+ case UnaryOperator::Deref: VisitDeref(U, Pred, Dst); break;
+ case UnaryOperator::Plus: Visit(U->getSubExpr(), Pred, Dst); break;
+ case UnaryOperator::SizeOf: VisitSizeOfExpr(U, Pred, Dst); break;
+ default: VisitUnaryOperator(U, Pred, Dst); break;
+ }
+
+ break;
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Block entrance. (Update counters).
+//===----------------------------------------------------------------------===//
+
+bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*,
+ GRBlockCounter BC) {
+
+ return BC.getNumVisited(B->getBlockID()) < 3;
+}
+
+//===----------------------------------------------------------------------===//
+// Branch processing.
+//===----------------------------------------------------------------------===//
+
ValueState* GRExprEngine::MarkBranch(ValueState* St, Stmt* Terminator,
bool branchTaken) {
@@ -194,12 +404,6 @@
}
}
-bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*,
- GRBlockCounter BC) {
-
- return BC.getNumVisited(B->getBlockID()) < 3;
-}
-
void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term,
BranchNodeBuilder& builder) {
@@ -236,7 +440,6 @@
}
}
-
// Process the true branch.
bool isFeasible = false;
@@ -303,6 +506,27 @@
builder.generateNode(I, St);
}
+
+void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
+ NodeTy* Pred, NodeSet& Dst) {
+
+ assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
+
+ ValueState* St = GetState(Pred);
+ RVal X = GetBlkExprRVal(St, Ex);
+
+ assert (X.isUndef());
+
+ Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
+
+ assert (SE);
+
+ X = GetBlkExprRVal(St, SE);
+
+ // Make sure that we invalidate the previous binding.
+ MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, X, true, true));
+}
+
/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
/// nodes by processing the 'effects' of a switch statement.
void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) {
@@ -401,6 +625,9 @@
builder.generateDefaultCaseNode(DefaultSt);
}
+//===----------------------------------------------------------------------===//
+// Transfer functions: logical operations ('&&', '||').
+//===----------------------------------------------------------------------===//
void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
NodeSet& Dst) {
@@ -461,51 +688,9 @@
}
}
-
-void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) {
-
- Builder = &builder;
- StmtEntryNode = builder.getLastNode();
- CurrentStmt = S;
- NodeSet Dst;
-
- // Set up our simple checks.
-
- if (!MsgExprChecks.empty())
- Builder->setObjCMsgExprAuditors(
- (GRAuditor<ValueState>**) &MsgExprChecks[0],
- (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size()));
-
-
- if (!CallChecks.empty())
- Builder->setCallExprAuditors(
- (GRAuditor<ValueState>**) &CallChecks[0],
- (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size()));
-
- // Create the cleaned state.
-
- CleanedState = StateMgr.RemoveDeadBindings(StmtEntryNode->getState(),
- CurrentStmt, Liveness);
-
- Builder->SetCleanedState(CleanedState);
-
- // Visit the statement.
-
- Visit(S, StmtEntryNode, Dst);
-
- // If no nodes were generated, generate a new node that has all the
- // dead mappings removed.
-
- if (Dst.size() == 1 && *Dst.begin() == StmtEntryNode)
- builder.generateNode(S, GetState(StmtEntryNode), StmtEntryNode);
-
- // NULL out these variables to cleanup.
-
- CurrentStmt = NULL;
- StmtEntryNode = NULL;
- Builder = NULL;
- CleanedState = NULL;
-}
+//===----------------------------------------------------------------------===//
+// Transfer functions: DeclRefExprs (loads, getting l-values).
+//===----------------------------------------------------------------------===//
void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){
@@ -523,6 +708,10 @@
MakeNode(Dst, D, Pred, SetBlkExprRVal(St, D, Y));
}
+//===----------------------------------------------------------------------===//
+// Transfer function: Function calls.
+//===----------------------------------------------------------------------===//
+
void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred,
CallExpr::arg_iterator AI,
CallExpr::arg_iterator AE,
@@ -682,12 +871,120 @@
EvalCall(Dst, CE, cast<LVal>(L), *DI);
- if (!Builder->BuildSinks && Dst.size() == size)
- MakeNode(Dst, CE, *DI, St);
- }
- }
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+
+ if (!Builder->BuildSinks && Dst.size() == size)
+ MakeNode(Dst, CE, *DI, St);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Transfer function: Objective-C message expressions.
+//===----------------------------------------------------------------------===//
+
+void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred,
+ NodeSet& Dst){
+
+ VisitObjCMessageExprArgHelper(ME, ME->arg_begin(), ME->arg_end(),
+ Pred, Dst);
+}
+
+void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
+ ObjCMessageExpr::arg_iterator AI,
+ ObjCMessageExpr::arg_iterator AE,
+ NodeTy* Pred, NodeSet& Dst) {
+ if (AI == AE) {
+
+ // Process the receiver.
+
+ if (Expr* Receiver = ME->getReceiver()) {
+ NodeSet Tmp;
+ Visit(Receiver, Pred, Tmp);
+
+ for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+ VisitObjCMessageExprDispatchHelper(ME, *NI, Dst);
+
+ return;
+ }
+
+ VisitObjCMessageExprDispatchHelper(ME, Pred, Dst);
+ return;
+ }
+
+ NodeSet Tmp;
+ Visit(*AI, Pred, Tmp);
+
+ ++AI;
+
+ for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
+ VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst);
+}
+
+void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
+ NodeTy* Pred,
+ NodeSet& Dst) {
+
+ // FIXME: More logic for the processing the method call.
+
+ ValueState* St = GetState(Pred);
+
+ if (Expr* Receiver = ME->getReceiver()) {
+
+ RVal L = GetRVal(St, Receiver);
+
+ // Check for undefined control-flow or calls to NULL.
+
+ if (L.isUndef()) {
+ NodeTy* N = Builder->generateNode(ME, St, Pred);
+
+ if (N) {
+ N->markAsSink();
+ UndefReceivers.insert(N);
+ }
+
+ return;
+ }
+ }
+
+ // Check for any arguments that are uninitialized/undefined.
+
+ for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
+ I != E; ++I) {
+
+ if (GetRVal(St, *I).isUndef()) {
+
+ // Generate an error node for passing an uninitialized/undefined value
+ // as an argument to a message expression. This node is a sink.
+ NodeTy* N = Builder->generateNode(ME, St, Pred);
+
+ if (N) {
+ N->markAsSink();
+ MsgExprUndefArgs[N] = *I;
+ }
+
+ return;
+ }
+ }
+ // Dispatch to plug-in transfer function.
+
+ unsigned size = Dst.size();
+ SaveAndRestore<bool> OldSink(Builder->BuildSinks);
+
+ EvalObjCMessageExpr(Dst, ME, Pred);
+
+ // Handle the case where no nodes where generated. Auto-generate that
+ // contains the updated state if we aren't generating sinks.
+
+ if (!Builder->BuildSinks && Dst.size() == size)
+ MakeNode(Dst, ME, Pred, St);
}
+//===----------------------------------------------------------------------===//
+// Transfer functions: Miscellaneous statements.
+//===----------------------------------------------------------------------===//
+
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
NodeSet S1;
@@ -788,25 +1085,6 @@
}
-void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R,
- NodeTy* Pred, NodeSet& Dst) {
-
- assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex));
-
- ValueState* St = GetState(Pred);
- RVal X = GetBlkExprRVal(St, Ex);
-
- assert (X.isUndef());
-
- Expr* SE = (Expr*) cast<UndefinedVal>(X).getData();
-
- assert (SE);
-
- X = GetBlkExprRVal(St, SE);
-
- // Make sure that we invalidate the previous binding.
- MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, X, true, true));
-}
/// VisitSizeOfAlignOfTypeExpr - Transfer function for sizeof(type).
void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex,
@@ -1158,102 +1436,6 @@
VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
}
-
-void GRExprEngine::VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred,
- NodeSet& Dst){
- VisitObjCMessageExprArgHelper(ME, ME->arg_begin(), ME->arg_end(), Pred, Dst);
-}
-
-void GRExprEngine::VisitObjCMessageExprArgHelper(ObjCMessageExpr* ME,
- ObjCMessageExpr::arg_iterator AI,
- ObjCMessageExpr::arg_iterator AE,
- NodeTy* Pred, NodeSet& Dst) {
- if (AI == AE) {
-
- // Process the receiver.
-
- if (Expr* Receiver = ME->getReceiver()) {
- NodeSet Tmp;
- Visit(Receiver, Pred, Tmp);
-
- for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
- VisitObjCMessageExprDispatchHelper(ME, *NI, Dst);
-
- return;
- }
-
- VisitObjCMessageExprDispatchHelper(ME, Pred, Dst);
- return;
- }
-
- NodeSet Tmp;
- Visit(*AI, Pred, Tmp);
-
- ++AI;
-
- for (NodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI != NE; ++NI)
- VisitObjCMessageExprArgHelper(ME, AI, AE, *NI, Dst);
-}
-
-void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME,
- NodeTy* Pred, NodeSet& Dst) {
-
-
- // FIXME: More logic for the processing the method call.
-
- ValueState* St = GetState(Pred);
-
- if (Expr* Receiver = ME->getReceiver()) {
-
- RVal L = GetRVal(St, Receiver);
-
- // Check for undefined control-flow or calls to NULL.
-
- if (L.isUndef()) {
- NodeTy* N = Builder->generateNode(ME, St, Pred);
-
- if (N) {
- N->markAsSink();
- UndefReceivers.insert(N);
- }
-
- return;
- }
- }
-
- // Check for any arguments that are uninitialized/undefined.
-
- for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
- I != E; ++I) {
-
- if (GetRVal(St, *I).isUndef()) {
-
- NodeTy* N = Builder->generateNode(ME, St, Pred);
-
- if (N) {
- N->markAsSink();
- MsgExprUndefArgs[N] = *I;
- }
-
- return;
- }
- }
-
- // FIXME: Eventually we will properly handle the effects of a message
- // expr. For now invalidate all arguments passed in by references.
-
- for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
- I != E; ++I) {
-
- RVal V = GetRVal(St, *I);
-
- if (isa<LVal>(V))
- St = SetRVal(St, cast<LVal>(V), UnknownVal());
- }
-
- MakeNode(Dst, ME, Pred, St);
-}
-
void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
Expr* R = S->getRetValue();
@@ -1299,6 +1481,10 @@
Visit(R, Pred, Dst);
}
+//===----------------------------------------------------------------------===//
+// Transfer functions: Binary operators.
+//===----------------------------------------------------------------------===//
+
void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,
GRExprEngine::NodeTy* Pred,
GRExprEngine::NodeSet& Dst) {
@@ -1613,143 +1799,6 @@
UndefStores.insert(N);
}
-void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) {
-
- // FIXME: add metadata to the CFG so that we can disable
- // this check when we KNOW that there is no block-level subexpression.
- // The motivation is that this check requires a hashtable lookup.
-
- if (S != CurrentStmt && getCFG().isBlkExpr(S)) {
- Dst.Add(Pred);
- return;
- }
-
- switch (S->getStmtClass()) {
-
- default:
- // Cases we intentionally have "default" handle:
- // AddrLabelExpr, IntegerLiteral, CharacterLiteral
-
- Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
- break;
-
- case Stmt::AsmStmtClass:
- VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
- break;
-
- case Stmt::BinaryOperatorClass: {
- BinaryOperator* B = cast<BinaryOperator>(S);
-
- if (B->isLogicalOp()) {
- VisitLogicalExpr(B, Pred, Dst);
- break;
- }
- else if (B->getOpcode() == BinaryOperator::Comma) {
- ValueState* St = GetState(Pred);
- MakeNode(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS())));
- break;
- }
-
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- break;
- }
-
- case Stmt::CallExprClass: {
- CallExpr* C = cast<CallExpr>(S);
- VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
- break;
- }
-
- case Stmt::CastExprClass: {
- CastExpr* C = cast<CastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst);
- break;
- }
-
- // FIXME: ChooseExpr is really a constant. We need to fix
- // the CFG do not model them as explicit control-flow.
-
- case Stmt::ChooseExprClass: { // __builtin_choose_expr
- ChooseExpr* C = cast<ChooseExpr>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::CompoundAssignOperatorClass:
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
- break;
-
- case Stmt::ConditionalOperatorClass: { // '?' operator
- ConditionalOperator* C = cast<ConditionalOperator>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::DeclRefExprClass:
- VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst);
- break;
-
- case Stmt::DeclStmtClass:
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
- break;
-
- case Stmt::ImplicitCastExprClass: {
- ImplicitCastExpr* C = cast<ImplicitCastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst);
- break;
- }
-
- case Stmt::ObjCMessageExprClass: {
- VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst);
- break;
- }
-
- case Stmt::ParenExprClass:
- Visit(cast<ParenExpr>(S)->getSubExpr(), Pred, Dst);
- break;
-
- case Stmt::SizeOfAlignOfTypeExprClass:
- VisitSizeOfAlignOfTypeExpr(cast<SizeOfAlignOfTypeExpr>(S), Pred, Dst);
- break;
-
- case Stmt::StmtExprClass: {
- StmtExpr* SE = cast<StmtExpr>(S);
-
- ValueState* St = GetState(Pred);
-
- // FIXME: Not certain if we can have empty StmtExprs. If so, we should
- // probably just remove these from the CFG.
- assert (!SE->getSubStmt()->body_empty());
-
- if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin()))
- MakeNode(Dst, SE, Pred, SetRVal(St, SE, GetRVal(St, LastExpr)));
- else
- Dst.Add(Pred);
-
- break;
- }
-
- // FIXME: We may wish to always bind state to ReturnStmts so
- // that users can quickly query what was the state at the
- // exit points of a function.
-
- case Stmt::ReturnStmtClass:
- VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst); break;
-
- case Stmt::UnaryOperatorClass: {
- UnaryOperator* U = cast<UnaryOperator>(S);
-
- switch (U->getOpcode()) {
- case UnaryOperator::Deref: VisitDeref(U, Pred, Dst); break;
- case UnaryOperator::Plus: Visit(U->getSubExpr(), Pred, Dst); break;
- case UnaryOperator::SizeOf: VisitSizeOfExpr(U, Pred, Dst); break;
- default: VisitUnaryOperator(U, Pred, Dst); break;
- }
-
- break;
- }
- }
-}
//===----------------------------------------------------------------------===//
// "Assume" logic.
Modified: cfe/trunk/lib/Analysis/GRSimpleVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.cpp?rev=49752&r1=49751&r2=49752&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Tue Apr 15 18:06:53 2008
@@ -552,7 +552,7 @@
}
//===----------------------------------------------------------------------===//
-// Transfer function for Function Calls.
+// Transfer function for function calls.
//===----------------------------------------------------------------------===//
void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
@@ -590,3 +590,32 @@
Builder.MakeNode(Dst, CE, Pred, St);
}
+
+//===----------------------------------------------------------------------===//
+// Transfer function for Objective-C message expressions.
+//===----------------------------------------------------------------------===//
+
+void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+ GRExprEngine& Eng,
+ GRStmtNodeBuilder<ValueState>& Builder,
+ ObjCMessageExpr* ME,
+ ExplodedNode<ValueState>* Pred) {
+
+
+ // The basic transfer function logic for message expressions does nothing.
+ // We just invalidate all arguments passed in by references.
+
+ ValueStateManager& StateMgr = Eng.getStateManager();
+ ValueState* St = Builder.GetState(Pred);
+
+ for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end();
+ I != E; ++I) {
+
+ RVal V = StateMgr.GetRVal(St, *I);
+
+ if (isa<LVal>(V))
+ St = StateMgr.SetRVal(St, cast<LVal>(V), UnknownVal());
+ }
+
+ Builder.MakeNode(Dst, ME, Pred, St);
+}
Modified: cfe/trunk/lib/Analysis/GRSimpleVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.h?rev=49752&r1=49751&r2=49752&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.h (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.h Tue Apr 15 18:06:53 2008
@@ -63,6 +63,14 @@
CallExpr* CE, LVal L,
ExplodedNode<ValueState>* Pred);
+ virtual void EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& Dst,
+ GRExprEngine& Engine,
+ GRStmtNodeBuilder<ValueState>& Builder,
+ ObjCMessageExpr* ME,
+ ExplodedNode<ValueState>* Pred);
+
+
+
static void GeneratePathDiagnostic(PathDiagnostic& PD, ASTContext& Ctx,
ExplodedNode<ValueState>* N);
More information about the cfe-commits
mailing list