diff options
author | Ted Kremenek <kremenek@apple.com> | 2008-03-27 21:15:17 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2008-03-27 21:15:17 +0000 |
commit | e5d5c204c761cc3b2a6374a15b035420f207c7af (patch) | |
tree | 3a17ff2a287a423e6685351aa3639b522fb000bf /lib | |
parent | 0f9063c116b7c3b05d8042b5976463c2dae04861 (diff) |
Hooked up initial NSString interface checking to GRSimpleVals.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@48895 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Analysis/BasicObjCFoundationChecks.cpp | 46 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/GRSimpleVals.cpp | 2 |
3 files changed, 42 insertions, 14 deletions
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index 4d7a4d99db..d2a2dd6a51 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -32,16 +32,18 @@ namespace { class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck { - ASTContext &Ctx; - ValueStateManager* VMgr; - std::list<AnnotatedPath<ValueState> > Errors; + ASTContext &Ctx; + ValueStateManager* VMgr; + + typedef std::list<AnnotatedPath<ValueState> > ErrorsTy; + ErrorsTy Errors; - RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } + RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } - bool isNSString(ObjCInterfaceType* T, const char* suffix); - bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME); + bool isNSString(ObjCInterfaceType* T, const char* suffix); + bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME); - void RegisterError(NodeTy* N, Expr* E, const char *msg); + void RegisterError(NodeTy* N, Expr* E, const char *msg); public: BasicObjCFoundationChecks(ASTContext& ctx, ValueStateManager* vmgr) @@ -50,6 +52,9 @@ public: virtual ~BasicObjCFoundationChecks() {} virtual bool Audit(ExplodedNode<ValueState>* N); + + virtual void ReportResults(Diagnostic& D); + }; } // end anonymous namespace @@ -98,6 +103,10 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode<ValueState>* N) { return false; } +static inline bool isNil(RVal X) { + return isa<lval::ConcreteInt>(X); +} + //===----------------------------------------------------------------------===// // Error reporting. //===----------------------------------------------------------------------===// @@ -110,6 +119,26 @@ void BasicObjCFoundationChecks::RegisterError(NodeTy* N, Errors.back().push_back(N, msg, E); } +void BasicObjCFoundationChecks::ReportResults(Diagnostic& D) { + + // FIXME: Expand errors into paths. For now, just issue warnings. + + for (ErrorsTy::iterator I=Errors.begin(), E=Errors.end(); I!=E; ++I) { + + AnnotatedNode<ValueState>& AN = I->back(); + + unsigned diag = D.getCustomDiagID(Diagnostic::Warning, + AN.getString().c_str()); + + Stmt* S = cast<PostStmt>(AN.getNode()->getLocation()).getStmt(); + FullSourceLoc L(S->getLocStart(), Ctx.getSourceManager()); + + SourceRange R = AN.getExpr()->getSourceRange(); + + D.Report(diag, &AN.getString(), 1, &R, 1); + } +} + //===----------------------------------------------------------------------===// // NSString checking. //===----------------------------------------------------------------------===// @@ -139,10 +168,9 @@ bool BasicObjCFoundationChecks::AuditNSString(NodeTy* N, Expr * E = ME->getArg(0); RVal X = GetRVal(St, E); - if (isa<lval::ConcreteInt>(X)) { + if (isNil(X)) RegisterError(N, E, "Argument to NSString method 'compare:' cannot be nil."); - } } return false; diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index b6f164a57f..b70e21977b 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -411,14 +411,14 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { if (!MsgExprChecks.empty()) Builder->setObjCMsgExprAuditors( - (GRNodeAuditor<ValueState>**) &MsgExprChecks[0], - (GRNodeAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size())); + (GRAuditor<ValueState>**) &MsgExprChecks[0], + (GRAuditor<ValueState>**) (&MsgExprChecks[0] + MsgExprChecks.size())); if (!CallChecks.empty()) Builder->setCallExprAuditors( - (GRNodeAuditor<ValueState>**) &CallChecks[0], - (GRNodeAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size())); + (GRAuditor<ValueState>**) &CallChecks[0], + (GRAuditor<ValueState>**) (&CallChecks[0] + CallChecks.size())); // Create the cleaned state. diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 520f6246bf..94cedc0352 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -167,7 +167,7 @@ unsigned RunGRSimpleVals(CFG& cfg, Decl& CD, ASTContext& Ctx, CheckerState->undef_receivers_end(), "Receiver in message expression is an uninitialized value."); - + FoundationCheck.get()->ReportResults(Diag); #ifndef NDEBUG if (Visualize) CheckerState->ViewGraph(TrimGraph); #endif |