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