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 26namespace clang { 27class FunctionDecl; 28class ObjCMethodDecl; 29 30namespace ento { namespace objc_retain { 31 32/// An ArgEffect summarizes the retain count behavior on an argument or receiver 33/// to a function or method. 34enum 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 a pointer to a retain-counted object; on exit, the new 73 /// value of the pointer is a +0 value or NULL. 74 UnretainedOutParameter, 75 76 /// The argument is a pointer to a retain-counted object; on exit, the new 77 /// value of the pointer is a +1 value or NULL. 78 RetainedOutParameter, 79 80 /// The argument is treated as potentially escaping, meaning that 81 /// even when its reference count hits 0 it should be treated as still 82 /// possibly being alive as someone else *may* be holding onto the object. 83 MayEscape, 84 85 /// All typestate tracking of the object ceases. This is usually employed 86 /// when the effect of the call is completely unknown. 87 StopTracking, 88 89 /// All typestate tracking of the object ceases. Unlike StopTracking, 90 /// this is also enforced when the method body is inlined. 91 /// 92 /// In some cases, we obtain a better summary for this checker 93 /// by looking at the call site than by inlining the function. 94 /// Signifies that we should stop tracking the symbol even if 95 /// the function is inlined. 96 StopTrackingHard, 97 98 /// Performs the combined functionality of DecRef and StopTrackingHard. 99 /// 100 /// The models the effect that the called function decrements the reference 101 /// count of the argument and all typestate tracking on that argument 102 /// should cease. 103 DecRefAndStopTrackingHard, 104 105 /// Performs the combined functionality of DecRefMsg and StopTrackingHard. 106 /// 107 /// The models the effect that the called function decrements the reference 108 /// count of the argument and all typestate tracking on that argument 109 /// should cease. 110 DecRefMsgAndStopTrackingHard 111}; 112 113/// RetEffect summarizes a call's retain/release behavior with respect 114/// to its return value. 115class RetEffect { 116public: 117 enum Kind { 118 /// Indicates that no retain count information is tracked for 119 /// the return value. 120 NoRet, 121 /// Indicates that the returned value is an owned (+1) symbol. 122 OwnedSymbol, 123 /// Indicates that the returned value is an object with retain count 124 /// semantics but that it is not owned (+0). This is the default 125 /// for getters, etc. 126 NotOwnedSymbol, 127 /// Indicates that the object is not owned and controlled by the 128 /// Garbage collector. 129 GCNotOwnedSymbol, 130 /// Indicates that the return value is an owned object when the 131 /// receiver is also a tracked object. 132 OwnedWhenTrackedReceiver, 133 // Treat this function as returning a non-tracked symbol even if 134 // the function has been inlined. This is used where the call 135 // site summary is more presise than the summary indirectly produced 136 // by inlining the function 137 NoRetHard 138 }; 139 140 /// Determines the object kind of a tracked object. 141 enum ObjKind { 142 /// Indicates that the tracked object is a CF object. This is 143 /// important between GC and non-GC code. 144 CF, 145 /// Indicates that the tracked object is an Objective-C object. 146 ObjC, 147 /// Indicates that the tracked object could be a CF or Objective-C object. 148 AnyObj 149 }; 150 151private: 152 Kind K; 153 ObjKind O; 154 155 RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {} 156 157public: 158 Kind getKind() const { return K; } 159 160 ObjKind getObjKind() const { return O; } 161 162 bool isOwned() const { 163 return K == OwnedSymbol || K == OwnedWhenTrackedReceiver; 164 } 165 166 bool notOwned() const { 167 return K == NotOwnedSymbol; 168 } 169 170 bool operator==(const RetEffect &Other) const { 171 return K == Other.K && O == Other.O; 172 } 173 174 static RetEffect MakeOwnedWhenTrackedReceiver() { 175 return RetEffect(OwnedWhenTrackedReceiver, ObjC); 176 } 177 178 static RetEffect MakeOwned(ObjKind o) { 179 return RetEffect(OwnedSymbol, o); 180 } 181 static RetEffect MakeNotOwned(ObjKind o) { 182 return RetEffect(NotOwnedSymbol, o); 183 } 184 static RetEffect MakeGCNotOwned() { 185 return RetEffect(GCNotOwnedSymbol, ObjC); 186 } 187 static RetEffect MakeNoRet() { 188 return RetEffect(NoRet); 189 } 190 static RetEffect MakeNoRetHard() { 191 return RetEffect(NoRetHard); 192 } 193}; 194 195/// Encapsulates the retain count semantics on the arguments, return value, 196/// and receiver (if any) of a function/method call. 197/// 198/// Note that construction of these objects is not highly efficient. That 199/// is okay for clients where creating these objects isn't really a bottleneck. 200/// The purpose of the API is to provide something simple. The actual 201/// static analyzer checker that implements retain/release typestate 202/// tracking uses something more efficient. 203class CallEffects { 204 llvm::SmallVector<ArgEffect, 10> Args; 205 RetEffect Ret; 206 ArgEffect Receiver; 207 208 CallEffects(const RetEffect &R) : Ret(R) {} 209 210public: 211 /// Returns the argument effects for a call. 212 ArrayRef<ArgEffect> getArgs() const { return Args; } 213 214 /// Returns the effects on the receiver. 215 ArgEffect getReceiver() const { return Receiver; } 216 217 /// Returns the effect on the return value. 218 RetEffect getReturnValue() const { return Ret; } 219 220 /// Return the CallEfect for a given Objective-C method. 221 static CallEffects getEffect(const ObjCMethodDecl *MD); 222 223 /// Return the CallEfect for a given C/C++ function. 224 static CallEffects getEffect(const FunctionDecl *FD); 225}; 226 227}}} 228 229#endif 230 231