ObjCRetainCount.h revision 263508
1//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- 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 core data structures for retain count "summaries"
11//  for Objective-C and Core Foundation APIs.  These summaries are used
12//  by the static analyzer to summarize the retain/release effects of
13//  function and method calls.  This drives a path-sensitive typestate
14//  analysis in the static analyzer, but can also potentially be used by
15//  other clients.
16//
17//===----------------------------------------------------------------------===//
18
19#ifndef LLVM_CLANG_OBJCRETAINCOUNT_H
20#define LLVM_CLANG_OBJCRETAINCOUNT_H
21
22namespace clang { namespace ento { namespace objc_retain {
23
24/// An ArgEffect summarizes the retain count behavior on an argument or receiver
25/// to a function or method.
26enum ArgEffect {
27  /// There is no effect.
28  DoNothing,
29
30  /// The argument is treated as if an -autorelease message had been sent to
31  /// the referenced object.
32  Autorelease,
33
34  /// The argument is treated as if an -dealloc message had been sent to
35  /// the referenced object.
36  Dealloc,
37
38  /// The argument has its reference count decreased by 1.  This is as
39  /// if CFRelease has been called on the argument.
40  DecRef,
41
42  /// The argument has its reference count decreased by 1.  This is as
43  /// if a -release message has been sent to the argument.  This differs
44  /// in behavior from DecRef when GC is enabled.
45  DecRefMsg,
46
47  /// The argument has its reference count decreased by 1 to model
48  /// a transferred bridge cast under ARC.
49  DecRefBridgedTransferred,
50
51  /// The argument has its reference count increased by 1.  This is as
52  /// if a -retain message has been sent to the argument.  This differs
53  /// in behavior from IncRef when GC is enabled.
54  IncRefMsg,
55
56  /// The argument has its reference count increased by 1.  This is as
57  /// if CFRetain has been called on the argument.
58  IncRef,
59
60  /// The argument acts as if has been passed to CFMakeCollectable, which
61  /// transfers the object to the Garbage Collector under GC.
62  MakeCollectable,
63
64  /// The argument is treated as potentially escaping, meaning that
65  /// even when its reference count hits 0 it should be treated as still
66  /// possibly being alive as someone else *may* be holding onto the object.
67  MayEscape,
68
69  /// All typestate tracking of the object ceases.  This is usually employed
70  /// when the effect of the call is completely unknown.
71  StopTracking,
72
73  /// All typestate tracking of the object ceases.  Unlike StopTracking,
74  /// this is also enforced when the method body is inlined.
75  ///
76  /// In some cases, we obtain a better summary for this checker
77  /// by looking at the call site than by inlining the function.
78  /// Signifies that we should stop tracking the symbol even if
79  /// the function is inlined.
80  StopTrackingHard,
81
82  /// Performs the combined functionality of DecRef and StopTrackingHard.
83  ///
84  /// The models the effect that the called function decrements the reference
85  /// count of the argument and all typestate tracking on that argument
86  /// should cease.
87  DecRefAndStopTrackingHard,
88
89  /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
90  ///
91  /// The models the effect that the called function decrements the reference
92  /// count of the argument and all typestate tracking on that argument
93  /// should cease.
94  DecRefMsgAndStopTrackingHard
95};
96
97/// RetEffect summarizes a call's retain/release behavior with respect
98/// to its return value.
99class RetEffect {
100public:
101  enum Kind {
102    /// Indicates that no retain count information is tracked for
103    /// the return value.
104    NoRet,
105    /// Indicates that the returned value is an owned (+1) symbol.
106    OwnedSymbol,
107    /// Indicates that the returned value is an owned (+1) symbol and
108    /// that it should be treated as freshly allocated.
109    OwnedAllocatedSymbol,
110    /// Indicates that the returned value is an object with retain count
111    /// semantics but that it is not owned (+0).  This is the default
112    /// for getters, etc.
113    NotOwnedSymbol,
114    /// Indicates that the object is not owned and controlled by the
115    /// Garbage collector.
116    GCNotOwnedSymbol,
117    /// Indicates that the object is not owned and controlled by ARC.
118    ARCNotOwnedSymbol,
119    /// Indicates that the return value is an owned object when the
120    /// receiver is also a tracked object.
121    OwnedWhenTrackedReceiver,
122    // Treat this function as returning a non-tracked symbol even if
123    // the function has been inlined. This is used where the call
124    // site summary is more presise than the summary indirectly produced
125    // by inlining the function
126    NoRetHard
127  };
128
129  /// Determines the object kind of a tracked object.
130  enum ObjKind {
131    /// Indicates that the tracked object is a CF object.  This is
132    /// important between GC and non-GC code.
133    CF,
134    /// Indicates that the tracked object is an Objective-C object.
135    ObjC,
136    /// Indicates that the tracked object could be a CF or Objective-C object.
137    AnyObj
138  };
139
140private:
141  Kind K;
142  ObjKind O;
143
144  RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
145
146public:
147  Kind getKind() const { return K; }
148
149  ObjKind getObjKind() const { return O; }
150
151  bool isOwned() const {
152    return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
153    K == OwnedWhenTrackedReceiver;
154  }
155
156  bool notOwned() const {
157    return K == NotOwnedSymbol || K == ARCNotOwnedSymbol;
158  }
159
160  bool operator==(const RetEffect &Other) const {
161    return K == Other.K && O == Other.O;
162  }
163
164  static RetEffect MakeOwnedWhenTrackedReceiver() {
165    return RetEffect(OwnedWhenTrackedReceiver, ObjC);
166  }
167
168  static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
169    return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
170  }
171  static RetEffect MakeNotOwned(ObjKind o) {
172    return RetEffect(NotOwnedSymbol, o);
173  }
174  static RetEffect MakeGCNotOwned() {
175    return RetEffect(GCNotOwnedSymbol, ObjC);
176  }
177  static RetEffect MakeARCNotOwned() {
178    return RetEffect(ARCNotOwnedSymbol, ObjC);
179  }
180  static RetEffect MakeNoRet() {
181    return RetEffect(NoRet);
182  }
183  static RetEffect MakeNoRetHard() {
184    return RetEffect(NoRetHard);
185  }
186};
187
188/// Encapsulates the retain count semantics on the arguments, return value,
189/// and receiver (if any) of a function/method call.
190///
191/// Note that construction of these objects is not highly efficient.  That
192/// is okay for clients where creating these objects isn't really a bottleneck.
193/// The purpose of the API is to provide something simple.  The actual
194/// static analyzer checker that implements retain/release typestate
195/// tracking uses something more efficient.
196class CallEffects {
197  llvm::SmallVector<ArgEffect, 10> Args;
198  RetEffect Ret;
199  ArgEffect Receiver;
200
201  CallEffects(const RetEffect &R) : Ret(R) {}
202
203public:
204  /// Returns the argument effects for a call.
205  llvm::ArrayRef<ArgEffect> getArgs() const { return Args; }
206
207  /// Returns the effects on the receiver.
208  ArgEffect getReceiver() const { return Receiver; }
209
210  /// Returns the effect on the return value.
211  RetEffect getReturnValue() const { return Ret; }
212
213  /// Return the CallEfect for a given Objective-C method.
214  static CallEffects getEffect(const ObjCMethodDecl *MD);
215
216  /// Return the CallEfect for a given C/C++ function.
217  static CallEffects getEffect(const FunctionDecl *FD);
218};
219
220}}}
221
222#endif
223
224