clang  8.0.0
RetainCountChecker.h
Go to the documentation of this file.
1 //==--- RetainCountChecker.h - Checks for leaks and other issues -*- C++ -*--//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines the methods for RetainCountChecker, which implements
11 // a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
16 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
17 
19 #include "RetainCountDiagnostics.h"
20 #include "clang/AST/Attr.h"
21 #include "clang/AST/DeclCXX.h"
22 #include "clang/AST/DeclObjC.h"
23 #include "clang/AST/ParentMap.h"
37 #include "llvm/ADT/DenseMap.h"
38 #include "llvm/ADT/FoldingSet.h"
39 #include "llvm/ADT/ImmutableList.h"
40 #include "llvm/ADT/ImmutableMap.h"
41 #include "llvm/ADT/STLExtras.h"
42 #include "llvm/ADT/SmallString.h"
43 #include "llvm/ADT/StringExtras.h"
44 #include <cstdarg>
45 #include <utility>
46 
47 namespace clang {
48 namespace ento {
49 namespace retaincountchecker {
50 
51 /// Metadata on reference.
52 class RefVal {
53 public:
54  enum Kind {
55  Owned = 0, // Owning reference.
56  NotOwned, // Reference is not owned by still valid (not freed).
57  Released, // Object has been released.
58  ReturnedOwned, // Returned object passes ownership to caller.
59  ReturnedNotOwned, // Return object does not pass ownership to caller.
61  ErrorDeallocNotOwned, // -dealloc called on non-owned object.
62  ErrorUseAfterRelease, // Object used after released.
63  ErrorReleaseNotOwned, // Release of an object that was not owned.
65  ErrorLeak, // A memory leak due to excessive reference counts.
66  ErrorLeakReturned, // A memory leak due to the returning method not having
67  // the correct naming conventions.
70  };
71 
72  /// Tracks how an object referenced by an ivar has been used.
73  ///
74  /// This accounts for us not knowing if an arbitrary ivar is supposed to be
75  /// stored at +0 or +1.
76  enum class IvarAccessHistory {
77  None,
80  };
81 
82 private:
83  /// The number of outstanding retains.
84  unsigned Cnt;
85  /// The number of outstanding autoreleases.
86  unsigned ACnt;
87  /// The (static) type of the object at the time we started tracking it.
88  QualType T;
89 
90  /// The current state of the object.
91  ///
92  /// See the RefVal::Kind enum for possible values.
93  unsigned RawKind : 5;
94 
95  /// The kind of object being tracked (CF or ObjC or OSObject), if known.
96  ///
97  /// See the ObjKind enum for possible values.
98  unsigned RawObjectKind : 3;
99 
100  /// True if the current state and/or retain count may turn out to not be the
101  /// best possible approximation of the reference counting state.
102  ///
103  /// If true, the checker may decide to throw away ("override") this state
104  /// in favor of something else when it sees the object being used in new ways.
105  ///
106  /// This setting should not be propagated to state derived from this state.
107  /// Once we start deriving new states, it would be inconsistent to override
108  /// them.
109  unsigned RawIvarAccessHistory : 2;
110 
111  RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
112  IvarAccessHistory IvarAccess)
113  : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
114  RawObjectKind(static_cast<unsigned>(o)),
115  RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
116  assert(getKind() == k && "not enough bits for the kind");
117  assert(getObjKind() == o && "not enough bits for the object kind");
118  assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
119  }
120 
121 public:
122  Kind getKind() const { return static_cast<Kind>(RawKind); }
123 
124  ObjKind getObjKind() const {
125  return static_cast<ObjKind>(RawObjectKind);
126  }
127 
128  unsigned getCount() const { return Cnt; }
129  unsigned getAutoreleaseCount() const { return ACnt; }
130  unsigned getCombinedCounts() const { return Cnt + ACnt; }
131  void clearCounts() {
132  Cnt = 0;
133  ACnt = 0;
134  }
135  void setCount(unsigned i) {
136  Cnt = i;
137  }
138  void setAutoreleaseCount(unsigned i) {
139  ACnt = i;
140  }
141 
142  QualType getType() const { return T; }
143 
144  /// Returns what the analyzer knows about direct accesses to a particular
145  /// instance variable.
146  ///
147  /// If the object with this refcount wasn't originally from an Objective-C
148  /// ivar region, this should always return IvarAccessHistory::None.
150  return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
151  }
152 
153  bool isOwned() const {
154  return getKind() == Owned;
155  }
156 
157  bool isNotOwned() const {
158  return getKind() == NotOwned;
159  }
160 
161  bool isReturnedOwned() const {
162  return getKind() == ReturnedOwned;
163  }
164 
165  bool isReturnedNotOwned() const {
166  return getKind() == ReturnedNotOwned;
167  }
168 
169  /// Create a state for an object whose lifetime is the responsibility of the
170  /// current function, at least partially.
171  ///
172  /// Most commonly, this is an owned object with a retain count of +1.
174  return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
175  }
176 
177  /// Create a state for an object whose lifetime is not the responsibility of
178  /// the current function.
179  ///
180  /// Most commonly, this is an unowned object with a retain count of +0.
182  return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
183  }
184 
185  RefVal operator-(size_t i) const {
186  return RefVal(getKind(), getObjKind(), getCount() - i,
188  }
189 
190  RefVal operator+(size_t i) const {
191  return RefVal(getKind(), getObjKind(), getCount() + i,
193  }
194 
195  RefVal operator^(Kind k) const {
196  return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
198  }
199 
200  RefVal autorelease() const {
203  }
204 
209  }
210 
215  }
216 
217  // Comparison, profiling, and pretty-printing.
218  bool hasSameState(const RefVal &X) const {
219  return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
221  }
222 
223  bool operator==(const RefVal& X) const {
224  return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
225  }
226 
227  void Profile(llvm::FoldingSetNodeID& ID) const {
228  ID.Add(T);
229  ID.AddInteger(RawKind);
230  ID.AddInteger(Cnt);
231  ID.AddInteger(ACnt);
232  ID.AddInteger(RawObjectKind);
233  ID.AddInteger(RawIvarAccessHistory);
234  }
235 
236  void print(raw_ostream &Out) const;
237 };
238 
240  : public Checker< check::Bind,
241  check::DeadSymbols,
242  check::BeginFunction,
243  check::EndFunction,
244  check::PostStmt<BlockExpr>,
245  check::PostStmt<CastExpr>,
246  check::PostStmt<ObjCArrayLiteral>,
247  check::PostStmt<ObjCDictionaryLiteral>,
248  check::PostStmt<ObjCBoxedExpr>,
249  check::PostStmt<ObjCIvarRefExpr>,
250  check::PostCall,
251  check::RegionChanges,
252  eval::Assume,
253  eval::Call > {
254  mutable std::unique_ptr<RefCountBug> useAfterRelease, releaseNotOwned;
255  mutable std::unique_ptr<RefCountBug> deallocNotOwned;
256  mutable std::unique_ptr<RefCountBug> overAutorelease, returnNotOwnedForOwned;
257  mutable std::unique_ptr<RefCountBug> leakWithinFunction, leakAtReturn;
258 
259  mutable std::unique_ptr<RetainSummaryManager> Summaries;
260 public:
261  static constexpr const char *DeallocTagDescription = "DeallocSent";
262 
263  /// Track Objective-C and CoreFoundation objects.
264  bool TrackObjCAndCFObjects = false;
265 
266  /// Track sublcasses of OSObject.
267  bool TrackOSObjects = false;
268 
270 
271  RefCountBug *getLeakWithinFunctionBug(const LangOptions &LOpts) const;
272 
273  RefCountBug *getLeakAtReturnBug(const LangOptions &LOpts) const;
274 
275  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
276  // FIXME: We don't support ARC being turned on and off during one analysis.
277  // (nor, for that matter, do we support changing ASTContexts)
278  bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
279  if (!Summaries) {
280  Summaries.reset(new RetainSummaryManager(
281  Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects));
282  } else {
283  assert(Summaries->isARCEnabled() == ARCEnabled);
284  }
285  return *Summaries;
286  }
287 
288  RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
289  return getSummaryManager(C.getASTContext());
290  }
291 
292  void printState(raw_ostream &Out, ProgramStateRef State,
293  const char *NL, const char *Sep) const override;
294 
295  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
296  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
297  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
298 
299  void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
300  void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
301  void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
302 
303  void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
304 
305  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
306 
307  void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
308  CheckerContext &C) const;
309 
310  void processSummaryOfInlined(const RetainSummary &Summ,
311  const CallEvent &Call,
312  CheckerContext &C) const;
313 
314  bool evalCall(const CallExpr *CE, CheckerContext &C) const;
315 
316  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
317  bool Assumption) const;
318 
320  checkRegionChanges(ProgramStateRef state,
321  const InvalidatedSymbols *invalidated,
322  ArrayRef<const MemRegion *> ExplicitRegions,
324  const LocationContext* LCtx,
325  const CallEvent *Call) const;
326 
327  ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
328  ExplodedNode *Pred, RetEffect RE, RefVal X,
329  SymbolRef Sym, ProgramStateRef state) const;
330 
331  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
332  void checkBeginFunction(CheckerContext &C) const;
333  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
334 
335  ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
336  RefVal V, ArgEffect E, RefVal::Kind &hasErr,
337  CheckerContext &C) const;
338 
339  void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
341  CheckerContext &C) const;
342 
343  void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
344 
345  ProgramStateRef handleSymbolDeath(ProgramStateRef state,
346  SymbolRef sid, RefVal V,
347  SmallVectorImpl<SymbolRef> &Leaked) const;
348 
350  handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
351  const ProgramPointTag *Tag, CheckerContext &Ctx,
352  SymbolRef Sym,
353  RefVal V,
354  const ReturnStmt *S=nullptr) const;
355 
356  ExplodedNode *processLeaks(ProgramStateRef state,
358  CheckerContext &Ctx,
359  ExplodedNode *Pred = nullptr) const;
360 
361 private:
362  /// Perform the necessary checks and state adjustments at the end of the
363  /// function.
364  /// \p S Return statement, may be null.
365  ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
366 };
367 
368 //===----------------------------------------------------------------------===//
369 // RefBindings - State used to track object reference counts.
370 //===----------------------------------------------------------------------===//
371 
373 
375  RefVal Val);
376 
378 
379 /// Returns true if this stack frame is for an Objective-C method that is a
380 /// property getter or setter whose body has been synthesized by the analyzer.
381 inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
382  auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
383  if (!Method || !Method->isPropertyAccessor())
384  return false;
385 
387 }
388 
389 } // end namespace retaincountchecker
390 } // end namespace ento
391 } // end namespace clang
392 
393 #endif
RetainSummaryManager & getSummaryManager(CheckerContext &C) const
ObjKind
Determines the object kind of a tracked object.
A (possibly-)qualified type.
Definition: Type.h:638
ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val)
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:30
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
LineState State
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:50
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
Definition: ExprObjC.h:171
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:2998
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:106
Defines the clang::LangOptions interface.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
Definition: Expr.h:5177
#define bool
Definition: stdbool.h:31
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
Definition: ExprObjC.h:288
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Definition: Stmt.h:2443
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:40
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Definition: SVals.h:76
ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym)
A class responsible for cleaning up unused symbols.
ObjCBoxedExpr - used for generalized expression boxing.
Definition: ExprObjC.h:117
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:171
const Decl * getDecl() const
const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition: ExprObjC.h:513
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
Definition: SemaDecl.cpp:13954
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...
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2396
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...
AnalysisDeclContext * getAnalysisDeclContext() const
const LangOptions & getLangOpts() const
Definition: ASTContext.h:707
RetEffect summarizes a call&#39;s retain/release behavior with respect to its return value.