123 lines · c
1//== RetainCountDiagnostics.h - Checks for leaks and other issues -*- C++ -*--//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines diagnostics for RetainCountChecker, which implements10// a reference count checker for Core Foundation and Cocoa on (Mac OS X).11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H15#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H16 17#include "clang/Analysis/PathDiagnostic.h"18#include "clang/Analysis/RetainSummaryManager.h"19#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"20#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"21#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"22 23namespace clang {24namespace ento {25namespace retaincountchecker {26 27class RefCountBug : public BugType {28 StringRef ReportMessage;29 30public:31 RefCountBug(const CheckerFrontend *CF, StringRef Desc, StringRef ReportMsg,32 bool SuppressOnSink = false)33 : BugType(CF, Desc, categories::MemoryRefCount, SuppressOnSink),34 ReportMessage(ReportMsg) {}35 StringRef getReportMessage() const { return ReportMessage; }36};37 38class RefCountFrontend : public CheckerFrontend {39public:40 const RefCountBug UseAfterRelease{41 this, "Use-after-release",42 "Reference-counted object is used after it is released"};43 const RefCountBug ReleaseNotOwned{44 this, "Bad release",45 "Incorrect decrement of the reference count of an object that is not "46 "owned at this point by the caller"};47 const RefCountBug DeallocNotOwned{48 this, "-dealloc sent to non-exclusively owned object",49 "-dealloc sent to object that may be referenced elsewhere"};50 const RefCountBug FreeNotOwned{51 this, "freeing non-exclusively owned object",52 "'free' called on an object that may be referenced elsewhere"};53 const RefCountBug OverAutorelease{this, "Object autoreleased too many times",54 "Object autoreleased too many times"};55 const RefCountBug ReturnNotOwnedForOwned{56 this, "Method should return an owned object",57 "Object with a +0 retain count returned to caller where a +1 (owning) "58 "retain count is expected"};59 // For these two bug types the report message will be generated dynamically60 // by `RefLeakReport::createDescription` so the empty string taken from the61 // BugType will be ignored (overwritten).62 const RefCountBug LeakWithinFunction{this, "Leak", /*ReportMsg=*/"",63 /*SuppressOnSink=*/true};64 const RefCountBug LeakAtReturn{this, "Leak of returned object",65 /*ReportMsg=*/"", /*SuppressOnSink=*/true};66};67 68class RefCountReport : public PathSensitiveBugReport {69protected:70 SymbolRef Sym;71 bool isLeak = false;72 73public:74 RefCountReport(const RefCountBug &D, const LangOptions &LOpts,75 ExplodedNode *n, SymbolRef sym, bool isLeak = false,76 bool IsReleaseUnowned = false);77 78 RefCountReport(const RefCountBug &D, const LangOptions &LOpts,79 ExplodedNode *n, SymbolRef sym,80 StringRef endText);81 82 ArrayRef<SourceRange> getRanges() const override {83 if (!isLeak)84 return PathSensitiveBugReport::getRanges();85 return {};86 }87};88 89class RefLeakReport : public RefCountReport {90 const MemRegion *AllocFirstBinding = nullptr;91 const MemRegion *AllocBindingToReport = nullptr;92 const Stmt *AllocStmt = nullptr;93 PathDiagnosticLocation Location;94 95 // Finds the function declaration where a leak warning for the parameter96 // 'sym' should be raised.97 void deriveParamLocation(CheckerContext &Ctx);98 // Finds the location where the leaking object is allocated.99 void deriveAllocLocation(CheckerContext &Ctx);100 // Produces description of a leak warning which is printed on the console.101 void createDescription(CheckerContext &Ctx);102 // Finds the binding that we should use in a leak warning.103 void findBindingToReport(CheckerContext &Ctx, ExplodedNode *Node);104 105public:106 RefLeakReport(const RefCountBug &D, const LangOptions &LOpts, ExplodedNode *n,107 SymbolRef sym, CheckerContext &Ctx);108 PathDiagnosticLocation getLocation() const override {109 assert(Location.isValid());110 return Location;111 }112 113 PathDiagnosticLocation getEndOfPath() const {114 return PathSensitiveBugReport::getLocation();115 }116};117 118} // end namespace retaincountchecker119} // end namespace ento120} // end namespace clang121 122#endif123