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