diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index aa392b08608..aab5552f666 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1867,6 +1867,15 @@ static inline bool contains(const SmallVectorImpl<ArgEffect>& V, return false; } +static bool isNumericLiteralExpression(const Expr *E) { + // FIXME: This set of cases was copied from SemaExprObjC. + return isa<IntegerLiteral>(E) || + isa<CharacterLiteral>(E) || + isa<FloatingLiteral>(E) || + isa<ObjCBoolLiteralExpr>(E) || + isa<CXXBoolLiteralExpr>(E); +} + static bool isPropertyAccess(const Stmt *S, ParentMap &PM) { unsigned maxDepth = 4; while (S && maxDepth) { @@ -1916,6 +1925,24 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, else if (isa<ObjCDictionaryLiteral>(S)) { os << "NSDictionary literal is an object with a +0 retain count"; } + else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) { + if (isNumericLiteralExpression(BL->getSubExpr())) + os << "NSNumber literal is an object with a +0 retain count"; + else { + const ObjCInterfaceDecl *BoxClass = 0; + if (const ObjCMethodDecl *Method = BL->getBoxingMethod()) + BoxClass = Method->getClassInterface(); + + // We should always be able to find the boxing class interface, + // but consider this future-proofing. + if (BoxClass) + os << *BoxClass << " b"; + else + os << "B"; + + os << "oxed expression produces an object with a +0 retain count"; + } + } else { if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { // Get the name of the callee (if it is available). @@ -2324,6 +2351,7 @@ class RetainCountChecker check::PostStmt<CXXConstructExpr>, check::PostStmt<ObjCArrayLiteral>, check::PostStmt<ObjCDictionaryLiteral>, + check::PostStmt<ObjCBoxedExpr>, check::PostObjCMessage, check::PreStmt<ReturnStmt>, check::RegionChanges, @@ -2470,6 +2498,8 @@ public: void checkPostStmt(const CXXConstructExpr *CE, CheckerContext &C) const; void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const; void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const; + void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const; + void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const; void checkSummary(const RetainSummary &Summ, const CallOrObjCMessage &Call, @@ -2721,6 +2751,21 @@ void RetainCountChecker::checkPostStmt(const ObjCDictionaryLiteral *DL, processObjCLiterals(C, DL); } +void RetainCountChecker::checkPostStmt(const ObjCBoxedExpr *Ex, + CheckerContext &C) const { + const ExplodedNode *Pred = C.getPredecessor(); + const LocationContext *LCtx = Pred->getLocationContext(); + ProgramStateRef State = Pred->getState(); + + if (SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) { + QualType ResultTy = Ex->getType(); + State = State->set<RefBindings>(Sym, RefVal::makeNotOwned(RetEffect::ObjC, + ResultTy)); + } + + C.addTransition(State); +} + void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const { ProgramStateRef state = C.getState(); |