diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2018-11-30 02:18:23 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2018-11-30 02:18:23 +0000 |
| commit | 62db886062f841cb84fca6d32ec7cc91931400a2 (patch) | |
| tree | 270e6a5b44317f8903484cb3bfc603d687dd0287 /clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp | |
| parent | 3bdbeb155b3fd30e86df2accc324595fa06a47a5 (diff) | |
| download | bcm5719-llvm-62db886062f841cb84fca6d32ec7cc91931400a2.tar.gz bcm5719-llvm-62db886062f841cb84fca6d32ec7cc91931400a2.zip | |
[analyzer] [NFC] Minor refactoring of RetainCountDiagnostics
Move visitors to the implementation file, move a complicated logic into
a function.
Differential Revision: https://reviews.llvm.org/D55036
llvm-svn: 347946
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp | 198 |
1 files changed, 134 insertions, 64 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp index ce824ba0777..97ee9580c2b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -113,6 +113,121 @@ static bool shouldGenerateNote(llvm::raw_string_ostream &os, return true; } +static void generateDiagnosticsForCallLike( + ProgramStateRef CurrSt, + const LocationContext *LCtx, + const RefVal &CurrV, + SymbolRef &Sym, + const Stmt *S, + llvm::raw_string_ostream &os) { + if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { + // Get the name of the callee (if it is available) + // from the tracked SVal. + SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx); + const FunctionDecl *FD = X.getAsFunctionDecl(); + + // If failed, try to get it from AST. + if (!FD) + FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); + + if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) { + os << "Call to method '" << MD->getQualifiedNameAsString() << '\''; + } else if (FD) { + os << "Call to function '" << FD->getQualifiedNameAsString() << '\''; + } else { + os << "function call"; + } + } else { + assert(isa<ObjCMessageExpr>(S)); + CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager(); + CallEventRef<ObjCMethodCall> Call = + Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx); + + switch (Call->getMessageKind()) { + case OCM_Message: + os << "Method"; + break; + case OCM_PropertyAccess: + os << "Property"; + break; + case OCM_Subscript: + os << "Subscript"; + break; + } + } + + if (CurrV.getObjKind() == RetEffect::CF) { + os << " returns a Core Foundation object of type " + << Sym->getType().getAsString() << " with a "; + } else if (CurrV.getObjKind() == RetEffect::OS) { + os << " returns an OSObject of type " << getPrettyTypeName(Sym->getType()) + << " with a "; + } else if (CurrV.getObjKind() == RetEffect::Generalized) { + os << " returns an object of type " << Sym->getType().getAsString() + << " with a "; + } else { + assert(CurrV.getObjKind() == RetEffect::ObjC); + QualType T = Sym->getType(); + if (!isa<ObjCObjectPointerType>(T)) { + os << " returns an Objective-C object with a "; + } else { + const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T); + os << " returns an instance of " << PT->getPointeeType().getAsString() + << " with a "; + } + } + + if (CurrV.isOwned()) { + os << "+1 retain count"; + } else { + assert(CurrV.isNotOwned()); + os << "+0 retain count"; + } +} + +namespace clang { +namespace ento { +namespace retaincountchecker { + +class CFRefReportVisitor : public BugReporterVisitor { +protected: + SymbolRef Sym; + const SummaryLogTy &SummaryLog; + +public: + CFRefReportVisitor(SymbolRef sym, const SummaryLogTy &log) + : Sym(sym), SummaryLog(log) {} + + void Profile(llvm::FoldingSetNodeID &ID) const override { + static int x = 0; + ID.AddPointer(&x); + ID.AddPointer(Sym); + } + + std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, + BugReporterContext &BRC, + BugReport &BR) override; + + std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override; +}; + +class CFRefLeakReportVisitor : public CFRefReportVisitor { +public: + CFRefLeakReportVisitor(SymbolRef sym, + const SummaryLogTy &log) + : CFRefReportVisitor(sym, log) {} + + std::shared_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override; +}; + +} // end namespace retaincountchecker +} // end namespace ento +} // end namespace clang + std::shared_ptr<PathDiagnosticPiece> CFRefReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC, BugReport &BR) { @@ -122,7 +237,8 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, return nullptr; // Check if the type state has changed. - ProgramStateRef PrevSt = N->getFirstPred()->getState(); + const ExplodedNode *PrevNode = N->getFirstPred(); + ProgramStateRef PrevSt = PrevNode->getState(); ProgramStateRef CurrSt = N->getState(); const LocationContext *LCtx = N->getLocationContext(); @@ -172,69 +288,7 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N, } else if (isa<ObjCIvarRefExpr>(S)) { os << "Object loaded from instance variable"; } else { - if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { - // Get the name of the callee (if it is available) - // from the tracked SVal. - SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx); - const FunctionDecl *FD = X.getAsFunctionDecl(); - - // If failed, try to get it from AST. - if (!FD) - FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl()); - - if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) { - os << "Call to method '" << MD->getQualifiedNameAsString() << '\''; - } else if (FD) { - os << "Call to function '" << FD->getQualifiedNameAsString() << '\''; - } else { - os << "function call"; - } - } else { - assert(isa<ObjCMessageExpr>(S)); - CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager(); - CallEventRef<ObjCMethodCall> Call - = Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx); - - switch (Call->getMessageKind()) { - case OCM_Message: - os << "Method"; - break; - case OCM_PropertyAccess: - os << "Property"; - break; - case OCM_Subscript: - os << "Subscript"; - break; - } - } - - if (CurrV.getObjKind() == RetEffect::CF) { - os << " returns a Core Foundation object of type " - << Sym->getType().getAsString() << " with a "; - } else if (CurrV.getObjKind() == RetEffect::OS) { - os << " returns an OSObject of type " - << getPrettyTypeName(Sym->getType()) << " with a "; - } else if (CurrV.getObjKind() == RetEffect::Generalized) { - os << " returns an object of type " << Sym->getType().getAsString() - << " with a "; - } else { - assert (CurrV.getObjKind() == RetEffect::ObjC); - QualType T = Sym->getType(); - if (!isa<ObjCObjectPointerType>(T)) { - os << " returns an Objective-C object with a "; - } else { - const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T); - os << " returns an instance of " - << PT->getPointeeType().getAsString() << " with a "; - } - } - - if (CurrV.isOwned()) { - os << "+1 retain count"; - } else { - assert (CurrV.isNotOwned()); - os << "+0 retain count"; - } + generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os); } PathDiagnosticLocation Pos(S, BRC.getSourceManager(), @@ -500,6 +554,22 @@ CFRefLeakReportVisitor::getEndPath(BugReporterContext &BRC, return std::make_shared<PathDiagnosticEventPiece>(L, os.str()); } +CFRefReport::CFRefReport(CFRefBug &D, const LangOptions &LOpts, + const SummaryLogTy &Log, ExplodedNode *n, + SymbolRef sym, bool registerVisitor) + : BugReport(D, D.getDescription(), n), Sym(sym) { + if (registerVisitor) + addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, Log)); +} + +CFRefReport::CFRefReport(CFRefBug &D, const LangOptions &LOpts, + const SummaryLogTy &Log, ExplodedNode *n, + SymbolRef sym, StringRef endText) + : BugReport(D, D.getDescription(), endText, n) { + + addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, Log)); +} + void CFRefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) { const SourceManager& SMgr = Ctx.getSourceManager(); |

