]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / lib / StaticAnalyzer / Checkers / RetainCountChecker / RetainCountChecker.h
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
17 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
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"
23 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
24 #include "clang/Analysis/PathDiagnostic.h"
25 #include "clang/Analysis/RetainSummaryManager.h"
26 #include "clang/Basic/LangOptions.h"
27 #include "clang/Basic/SourceManager.h"
28 #include "clang/Analysis/SelectorExtras.h"
29 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
30 #include "clang/StaticAnalyzer/Core/Checker.h"
31 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
32 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
33 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
34 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
35 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.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.
59     ERROR_START,
60     ErrorDeallocNotOwned, // -dealloc called on non-owned object.
61     ErrorUseAfterRelease, // Object used after released.
62     ErrorReleaseNotOwned, // Release of an object that was not owned.
63     ERROR_LEAK_START,
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.
67     ErrorOverAutorelease,
68     ErrorReturnedNotOwned
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,
77     AccessedDirectly,
78     ReleasedAfterDirectAccess
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.
148   IvarAccessHistory getIvarAccessHistory() const {
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.
172   static RefVal makeOwned(ObjKind o, QualType t) {
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.
180   static RefVal makeNotOwned(ObjKind o, QualType t) {
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,
186                   getAutoreleaseCount(), getType(), getIvarAccessHistory());
187   }
188
189   RefVal operator+(size_t i) const {
190     return RefVal(getKind(), getObjKind(), getCount() + i,
191                   getAutoreleaseCount(), getType(), getIvarAccessHistory());
192   }
193
194   RefVal operator^(Kind k) const {
195     return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
196                   getType(), getIvarAccessHistory());
197   }
198
199   RefVal autorelease() const {
200     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
201                   getType(), getIvarAccessHistory());
202   }
203
204   RefVal withIvarAccess() const {
205     assert(getIvarAccessHistory() == IvarAccessHistory::None);
206     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
207                   getType(), IvarAccessHistory::AccessedDirectly);
208   }
209
210   RefVal releaseViaIvar() const {
211     assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
212     return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
213                   getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
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 &&
219            getIvarAccessHistory() == X.getIvarAccessHistory();
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
238 class RetainCountChecker
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
278   RetainCountChecker() {};
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
318   ProgramStateRef
319   checkRegionChanges(ProgramStateRef state,
320                      const InvalidatedSymbols *invalidated,
321                      ArrayRef<const MemRegion *> ExplicitRegions,
322                      ArrayRef<const MemRegion *> Regions,
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
351   ProgramStateRef
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,
359                              SmallVectorImpl<SymbolRef> &Leaked,
360                              CheckerContext &Ctx,
361                              ExplodedNode *Pred = nullptr) const;
362
363   const CheckerProgramPointTag &getDeallocSentTag() const {
364     return DeallocSentTag;
365   }
366
367   const CheckerProgramPointTag &getCastFailTag() const {
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
382 const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
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
391   return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
392 }
393
394 } // end namespace retaincountchecker
395 } // end namespace ento
396 } // end namespace clang
397
398 #endif