Home | History | Annotate | Download | only in Checkers
      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 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.
    115 class RetEffect {
    116 public:
    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 owned (+1) symbol and
    124     /// that it should be treated as freshly allocated.
    125     OwnedAllocatedSymbol,
    126     /// Indicates that the returned value is an object with retain count
    127     /// semantics but that it is not owned (+0).  This is the default
    128     /// for getters, etc.
    129     NotOwnedSymbol,
    130     /// Indicates that the object is not owned and controlled by the
    131     /// Garbage collector.
    132     GCNotOwnedSymbol,
    133     /// Indicates that the return value is an owned object when the
    134     /// receiver is also a tracked object.
    135     OwnedWhenTrackedReceiver,
    136     // Treat this function as returning a non-tracked symbol even if
    137     // the function has been inlined. This is used where the call
    138     // site summary is more presise than the summary indirectly produced
    139     // by inlining the function
    140     NoRetHard
    141   };
    142 
    143   /// Determines the object kind of a tracked object.
    144   enum ObjKind {
    145     /// Indicates that the tracked object is a CF object.  This is
    146     /// important between GC and non-GC code.
    147     CF,
    148     /// Indicates that the tracked object is an Objective-C object.
    149     ObjC,
    150     /// Indicates that the tracked object could be a CF or Objective-C object.
    151     AnyObj
    152   };
    153 
    154 private:
    155   Kind K;
    156   ObjKind O;
    157 
    158   RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
    159 
    160 public:
    161   Kind getKind() const { return K; }
    162 
    163   ObjKind getObjKind() const { return O; }
    164 
    165   bool isOwned() const {
    166     return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
    167     K == OwnedWhenTrackedReceiver;
    168   }
    169 
    170   bool notOwned() const {
    171     return K == NotOwnedSymbol;
    172   }
    173 
    174   bool operator==(const RetEffect &Other) const {
    175     return K == Other.K && O == Other.O;
    176   }
    177 
    178   static RetEffect MakeOwnedWhenTrackedReceiver() {
    179     return RetEffect(OwnedWhenTrackedReceiver, ObjC);
    180   }
    181 
    182   static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
    183     return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
    184   }
    185   static RetEffect MakeNotOwned(ObjKind o) {
    186     return RetEffect(NotOwnedSymbol, o);
    187   }
    188   static RetEffect MakeGCNotOwned() {
    189     return RetEffect(GCNotOwnedSymbol, ObjC);
    190   }
    191   static RetEffect MakeNoRet() {
    192     return RetEffect(NoRet);
    193   }
    194   static RetEffect MakeNoRetHard() {
    195     return RetEffect(NoRetHard);
    196   }
    197 };
    198 
    199 /// Encapsulates the retain count semantics on the arguments, return value,
    200 /// and receiver (if any) of a function/method call.
    201 ///
    202 /// Note that construction of these objects is not highly efficient.  That
    203 /// is okay for clients where creating these objects isn't really a bottleneck.
    204 /// The purpose of the API is to provide something simple.  The actual
    205 /// static analyzer checker that implements retain/release typestate
    206 /// tracking uses something more efficient.
    207 class CallEffects {
    208   llvm::SmallVector<ArgEffect, 10> Args;
    209   RetEffect Ret;
    210   ArgEffect Receiver;
    211 
    212   CallEffects(const RetEffect &R) : Ret(R) {}
    213 
    214 public:
    215   /// Returns the argument effects for a call.
    216   ArrayRef<ArgEffect> getArgs() const { return Args; }
    217 
    218   /// Returns the effects on the receiver.
    219   ArgEffect getReceiver() const { return Receiver; }
    220 
    221   /// Returns the effect on the return value.
    222   RetEffect getReturnValue() const { return Ret; }
    223 
    224   /// Return the CallEfect for a given Objective-C method.
    225   static CallEffects getEffect(const ObjCMethodDecl *MD);
    226 
    227   /// Return the CallEfect for a given C/C++ function.
    228   static CallEffects getEffect(const FunctionDecl *FD);
    229 };
    230 
    231 }}}
    232 
    233 #endif
    234 
    235