clang  20.0.0git
RetainCountChecker.h
Go to the documentation of this file.
1 //==--- RetainCountChecker.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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the methods for RetainCountChecker, which implements
10 // a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
15 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
16 
18 #include "RetainCountDiagnostics.h"
19 #include "clang/AST/Attr.h"
20 #include "clang/AST/DeclCXX.h"
21 #include "clang/AST/DeclObjC.h"
22 #include "clang/AST/ParentMap.h"
36 #include "llvm/ADT/DenseMap.h"
37 #include "llvm/ADT/FoldingSet.h"
38 #include "llvm/ADT/ImmutableList.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/SmallString.h"
41 #include "llvm/ADT/StringExtras.h"
42 #include <cstdarg>
43 #include <utility>
44 
45 namespace clang {
46 namespace ento {
47 namespace retaincountchecker {
48 
49 /// Metadata on reference.
50 class RefVal {
51 public:
52  enum Kind {
53  Owned = 0, // Owning reference.
54  NotOwned, // Reference is not owned by still valid (not freed).
55  Released, // Object has been released.
56  ReturnedOwned, // Returned object passes ownership to caller.
57  ReturnedNotOwned, // Return object does not pass ownership to caller.
59  ErrorDeallocNotOwned, // -dealloc called on non-owned object.
60  ErrorUseAfterRelease, // Object used after released.
61  ErrorReleaseNotOwned, // Release of an object that was not owned.
63  ErrorLeak, // A memory leak due to excessive reference counts.
64  ErrorLeakReturned, // A memory leak due to the returning method not having
65  // the correct naming conventions.
68  };
69 
70  /// Tracks how an object referenced by an ivar has been used.
71  ///
72  /// This accounts for us not knowing if an arbitrary ivar is supposed to be
73  /// stored at +0 or +1.
74  enum class IvarAccessHistory {
75  None,
78  };
79 
80 private:
81  /// The number of outstanding retains.
82  unsigned Cnt;
83  /// The number of outstanding autoreleases.
84  unsigned ACnt;
85  /// The (static) type of the object at the time we started tracking it.
86  QualType T;
87 
88  /// The current state of the object.
89  ///
90  /// See the RefVal::Kind enum for possible values.
91  unsigned RawKind : 5;
92 
93  /// The kind of object being tracked (CF or ObjC or OSObject), if known.
94  ///
95  /// See the ObjKind enum for possible values.
96  unsigned RawObjectKind : 3;
97 
98  /// True if the current state and/or retain count may turn out to not be the
99  /// best possible approximation of the reference counting state.
100  ///
101  /// If true, the checker may decide to throw away ("override") this state
102  /// in favor of something else when it sees the object being used in new ways.
103  ///
104  /// This setting should not be propagated to state derived from this state.
105  /// Once we start deriving new states, it would be inconsistent to override
106  /// them.
107  unsigned RawIvarAccessHistory : 2;
108 
109  RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
110  IvarAccessHistory IvarAccess)
111  : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
112  RawObjectKind(static_cast<unsigned>(o)),
113  RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
114  assert(getKind() == k && "not enough bits for the kind");
115  assert(getObjKind() == o && "not enough bits for the object kind");
116  assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
117  }
118 
119 public:
120  Kind getKind() const { return static_cast<Kind>(RawKind); }
121 
122  ObjKind getObjKind() const {
123  return static_cast<ObjKind>(RawObjectKind);
124  }
125 
126  unsigned getCount() const { return Cnt; }
127  unsigned getAutoreleaseCount() const { return ACnt; }
128  unsigned getCombinedCounts() const { return Cnt + ACnt; }
129  void clearCounts() {
130  Cnt = 0;
131  ACnt = 0;
132  }
133  void setCount(unsigned i) {
134  Cnt = i;
135  }
136  void setAutoreleaseCount(unsigned i) {
137  ACnt = i;
138  }
139 
140  QualType getType() const { return T; }
141 
142  /// Returns what the analyzer knows about direct accesses to a particular
143  /// instance variable.
144  ///
145  /// If the object with this refcount wasn't originally from an Objective-C
146  /// ivar region, this should always return IvarAccessHistory::None.
148  return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
149  }
150 
151  bool isOwned() const {
152  return getKind() == Owned;
153  }
154 
155  bool isNotOwned() const {
156  return getKind() == NotOwned;
157  }
158 
159  bool isReturnedOwned() const {
160  return getKind() == ReturnedOwned;
161  }
162 
163  bool isReturnedNotOwned() const {
164  return getKind() == ReturnedNotOwned;
165  }
166 
167  /// Create a state for an object whose lifetime is the responsibility of the
168  /// current function, at least partially.
169  ///
170  /// Most commonly, this is an owned object with a retain count of +1.
172  return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
173  }
174 
175  /// Create a state for an object whose lifetime is not the responsibility of
176  /// the current function.
177  ///
178  /// Most commonly, this is an unowned object with a retain count of +0.
180  return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
181  }
182 
183  RefVal operator-(size_t i) const {
184  return RefVal(getKind(), getObjKind(), getCount() - i,
186  }
187 
188  RefVal operator+(size_t i) const {
189  return RefVal(getKind(), getObjKind(), getCount() + i,
191  }
192 
193  RefVal operator^(Kind k) const {
194  return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
196  }
197 
198  RefVal autorelease() const {
201  }
202 
207  }
208 
213  }
214 
215  // Comparison, profiling, and pretty-printing.
216  bool hasSameState(const RefVal &X) const {
217  return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
218  getIvarAccessHistory() == X.getIvarAccessHistory();
219  }
220 
221  bool operator==(const RefVal& X) const {
222  return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
223  }
224 
225  void Profile(llvm::FoldingSetNodeID& ID) const {
226  ID.Add(T);
227  ID.AddInteger(RawKind);
228  ID.AddInteger(Cnt);
229  ID.AddInteger(ACnt);
230  ID.AddInteger(RawObjectKind);
231  ID.AddInteger(RawIvarAccessHistory);
232  }
233 
234  void print(raw_ostream &Out) const;
235 };
236 
238  : public Checker< check::Bind,
239  check::DeadSymbols,
240  check::BeginFunction,
241  check::EndFunction,
242  check::PostStmt<BlockExpr>,
243  check::PostStmt<CastExpr>,
244  check::PostStmt<ObjCArrayLiteral>,
245  check::PostStmt<ObjCDictionaryLiteral>,
246  check::PostStmt<ObjCBoxedExpr>,
247  check::PostStmt<ObjCIvarRefExpr>,
248  check::PostCall,
249  check::RegionChanges,
250  eval::Assume,
251  eval::Call > {
252 
253 public:
254  std::unique_ptr<RefCountBug> UseAfterRelease;
255  std::unique_ptr<RefCountBug> ReleaseNotOwned;
256  std::unique_ptr<RefCountBug> DeallocNotOwned;
257  std::unique_ptr<RefCountBug> FreeNotOwned;
258  std::unique_ptr<RefCountBug> OverAutorelease;
259  std::unique_ptr<RefCountBug> ReturnNotOwnedForOwned;
260  std::unique_ptr<RefCountBug> LeakWithinFunction;
261  std::unique_ptr<RefCountBug> LeakAtReturn;
262 
263  mutable std::unique_ptr<RetainSummaryManager> Summaries;
264 
265  static std::unique_ptr<CheckerProgramPointTag> DeallocSentTag;
266  static std::unique_ptr<CheckerProgramPointTag> CastFailTag;
267 
268  /// Track Objective-C and CoreFoundation objects.
269  bool TrackObjCAndCFObjects = false;
270 
271  /// Track sublcasses of OSObject.
272  bool TrackOSObjects = false;
273 
274  /// Track initial parameters (for the entry point) for NS/CF objects.
275  bool TrackNSCFStartParam = false;
276 
278 
280  if (!Summaries)
281  Summaries.reset(
283  return *Summaries;
284  }
285 
287  return getSummaryManager(C.getASTContext());
288  }
289 
290  void printState(raw_ostream &Out, ProgramStateRef State,
291  const char *NL, const char *Sep) const override;
292 
293  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
294  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
295  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
296 
297  void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
298  void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
299  void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
300 
301  void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
302 
303  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
304 
305  void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
306  CheckerContext &C) const;
307 
308  void processSummaryOfInlined(const RetainSummary &Summ,
309  const CallEvent &Call,
310  CheckerContext &C) const;
311 
312  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
313 
315  bool Assumption) const;
316 
319  const InvalidatedSymbols *invalidated,
320  ArrayRef<const MemRegion *> ExplicitRegions,
322  const LocationContext* LCtx,
323  const CallEvent *Call) const;
324 
326  ExplodedNode *Pred, RetEffect RE, RefVal X,
327  SymbolRef Sym, ProgramStateRef state) const;
328 
329  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
330  void checkBeginFunction(CheckerContext &C) const;
331  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
332 
334  RefVal V, ArgEffect E, RefVal::Kind &hasErr,
335  CheckerContext &C) const;
336 
338  SymbolRef Sym) const;
339 
340  void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
341  RefVal::Kind ErrorKind, SymbolRef Sym,
342  CheckerContext &C) const;
343 
344  void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
345 
347  SymbolRef sid, RefVal V,
348  SmallVectorImpl<SymbolRef> &Leaked) const;
349 
352  const ProgramPointTag *Tag, CheckerContext &Ctx,
353  SymbolRef Sym,
354  RefVal V,
355  const ReturnStmt *S=nullptr) const;
356 
359  CheckerContext &Ctx,
360  ExplodedNode *Pred = nullptr) const;
361 
363  return *DeallocSentTag;
364  }
365 
366  static const CheckerProgramPointTag &getCastFailTag() { return *CastFailTag; }
367 
368 private:
369  /// Perform the necessary checks and state adjustments at the end of the
370  /// function.
371  /// \p S Return statement, may be null.
372  ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
373 };
374 
375 //===----------------------------------------------------------------------===//
376 // RefBindings - State used to track object reference counts.
377 //===----------------------------------------------------------------------===//
378 
379 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
380 
381 /// Returns true if this stack frame is for an Objective-C method that is a
382 /// property getter or setter whose body has been synthesized by the analyzer.
383 inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
384  auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
385  if (!Method || !Method->isPropertyAccessor())
386  return false;
387 
389 }
390 
391 } // end namespace retaincountchecker
392 } // end namespace ento
393 } // end namespace clang
394 
395 #endif
#define V(N, I)
Definition: ASTContext.h:3346
static char ID
Definition: Arena.cpp:183
Expr * E
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
#define X(type, name)
Definition: Value.h:143
Defines the clang::LangOptions interface.
Defines the SourceManager interface.
LineState State
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:187
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:6396
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3550
This represents one expression.
Definition: Expr.h:110
It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...
const Decl * getDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp,...
Definition: ExprObjC.h:191
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:127
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:309
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:549
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Definition: ProgramPoint.h:38
A (possibly-)qualified type.
Definition: Type.h:941
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition: Stmt.h:3024
A trivial tuple used to represent a source range.
It represents a stack frame of the call stack (based on CallEvent).
Stmt - This represents one statement.
Definition: Stmt.h:84
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method.
Represents an abstract call to a function or method along a particular path.
Definition: CallEvent.h:153
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
Definition: Checker.h:505
RetEffect summarizes a call's retain/release behavior with respect to its return value.
Summary for a function with respect to ownership changes.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:55
Symbolic value.
Definition: SymExpr.h:30
A class responsible for cleaning up unused symbols.
bool operator==(const RefVal &X) const
IvarAccessHistory
Tracks how an object referenced by an ivar has been used.
IvarAccessHistory getIvarAccessHistory() const
Returns what the analyzer knows about direct accesses to a particular instance variable.
bool hasSameState(const RefVal &X) const
static RefVal makeOwned(ObjKind o, QualType t)
Create a state for an object whose lifetime is the responsibility of the current function,...
void Profile(llvm::FoldingSetNodeID &ID) const
static RefVal makeNotOwned(ObjKind o, QualType t)
Create a state for an object whose lifetime is not the responsibility of the current function.
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const
void checkSummary(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const
ProgramStateRef handleSymbolDeath(ProgramStateRef state, SymbolRef sid, RefVal V, SmallVectorImpl< SymbolRef > &Leaked) const
static std::unique_ptr< CheckerProgramPointTag > CastFailTag
bool TrackObjCAndCFObjects
Track Objective-C and CoreFoundation objects.
ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, bool Assumption) const
static std::unique_ptr< CheckerProgramPointTag > DeallocSentTag
void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange, RefVal::Kind ErrorKind, SymbolRef Sym, CheckerContext &C) const
const RefCountBug & errorKindToBugKind(RefVal::Kind ErrorKind, SymbolRef Sym) const
RetainSummaryManager & getSummaryManager(ASTContext &Ctx) const
static const CheckerProgramPointTag & getCastFailTag()
RetainSummaryManager & getSummaryManager(CheckerContext &C) const
void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const
ExplodedNode * checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C, ExplodedNode *Pred, RetEffect RE, RefVal X, SymbolRef Sym, ProgramStateRef state) const
ProgramStateRef handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred, const ProgramPointTag *Tag, CheckerContext &Ctx, SymbolRef Sym, RefVal V, const ReturnStmt *S=nullptr) const
ExplodedNode * processLeaks(ProgramStateRef state, SmallVectorImpl< SymbolRef > &Leaked, CheckerContext &Ctx, ExplodedNode *Pred=nullptr) const
ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, RefVal V, ArgEffect E, RefVal::Kind &hasErr, CheckerContext &C) const
void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const
std::unique_ptr< RetainSummaryManager > Summaries
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const override
See CheckerManager::runCheckersForPrintState.
bool evalCall(const CallEvent &Call, CheckerContext &C) const
void checkPostCall(const CallEvent &Call, CheckerContext &C) const
ProgramStateRef checkRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call) const
void processObjCLiterals(CheckerContext &C, const Expr *Ex) const
void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const
void processSummaryOfInlined(const RetainSummary &Summ, const CallEvent &Call, CheckerContext &C) const
static const CheckerProgramPointTag & getDeallocSentTag()
bool TrackNSCFStartParam
Track initial parameters (for the entry point) for NS/CF objects.
const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)
bool isSynthesizedAccessor(const StackFrameContext *SFC)
Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...
ObjKind
Determines the object kind of a tracked object.
llvm::DenseSet< SymbolRef > InvalidatedSymbols
Definition: Store.h:51
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T