<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Apologies! I’m really confused now how was it able to build without modules at all.<br class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Aug 17, 2018, at 8:24 PM, Bruno Cardoso Lopes <<a href="mailto:bruno.cardoso@gmail.com" class="">bruno.cardoso@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">Hi George,</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">This broke the modules build, reverted in r340117 for now. I can help</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">you figure out any module map change if necessary next week.</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">Thanks,</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">On Fri, Aug 17, 2018 at 6:46 PM George Karpenkov via cfe-commits</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class=""><</span><a href="mailto:cfe-commits@lists.llvm.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">cfe-commits@lists.llvm.org</a><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">> wrote:</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><blockquote type="cite" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><br class="">Author: george.karpenkov<br class="">Date: Fri Aug 17 18:45:50 2018<br class="">New Revision: 340114<br class=""><br class="">URL: <a href="http://llvm.org/viewvc/llvm-project?rev=340114&view=rev" class="">http://llvm.org/viewvc/llvm-project?rev=340114&view=rev</a><br class="">Log:<br class="">[analyzer] [NFC] Split up RetainSummaryManager from RetainCountChecker<br class=""><br class="">ARCMigrator is using code from RetainCountChecker, which is a layering<br class="">violation (and it also does it badly, by using a different header, and<br class="">then relying on implementation being present in a header file).<br class=""><br class="">This change splits up RetainSummaryManager into a separate library in<br class="">lib/Analysis, which can be used independently of a checker.<br class=""><br class="">Differential Revision: <a href="https://reviews.llvm.org/D50934" class="">https://reviews.llvm.org/D50934</a><br class=""><br class="">Added:<br class=""> cfe/trunk/include/clang/Analysis/RetainSummaryManager.h<br class=""> cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h<br class=""> cfe/trunk/lib/Analysis/RetainSummaryManager.cpp<br class="">Removed:<br class=""> cfe/trunk/include/clang/Analysis/ObjCRetainCount.h<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountSummaries.h<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/SelectorExtras.h<br class="">Modified:<br class=""> cfe/trunk/lib/ARCMigrate/CMakeLists.txt<br class=""> cfe/trunk/lib/ARCMigrate/ObjCMT.cpp<br class=""> cfe/trunk/lib/Analysis/CMakeLists.txt<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h<br class=""> cfe/trunk/lib/StaticAnalyzer/Checkers/TrustNonnullChecker.cpp<br class=""><br class="">Removed: cfe/trunk/include/clang/Analysis/ObjCRetainCount.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ObjCRetainCount.h?rev=340113&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/ObjCRetainCount.h?rev=340113&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Analysis/ObjCRetainCount.h (original)<br class="">+++ cfe/trunk/include/clang/Analysis/ObjCRetainCount.h (removed)<br class="">@@ -1,231 +0,0 @@<br class="">-//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//<br class="">-//<br class="">-// The LLVM Compiler Infrastructure<br class="">-//<br class="">-// This file is distributed under the University of Illinois Open Source<br class="">-// License. See LICENSE.TXT for details.<br class="">-//<br class="">-//===----------------------------------------------------------------------===//<br class="">-//<br class="">-// This file defines the core data structures for retain count "summaries"<br class="">-// for Objective-C and Core Foundation APIs. These summaries are used<br class="">-// by the static analyzer to summarize the retain/release effects of<br class="">-// function and method calls. This drives a path-sensitive typestate<br class="">-// analysis in the static analyzer, but can also potentially be used by<br class="">-// other clients.<br class="">-//<br class="">-//===----------------------------------------------------------------------===//<br class="">-<br class="">-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H<br class="">-#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H<br class="">-<br class="">-#include "clang/Basic/LLVM.h"<br class="">-#include "llvm/ADT/ArrayRef.h"<br class="">-#include "llvm/ADT/SmallVector.h"<br class="">-<br class="">-namespace clang {<br class="">-class FunctionDecl;<br class="">-class ObjCMethodDecl;<br class="">-<br class="">-namespace ento { namespace objc_retain {<br class="">-<br class="">-/// An ArgEffect summarizes the retain count behavior on an argument or receiver<br class="">-/// to a function or method.<br class="">-enum ArgEffect {<br class="">- /// There is no effect.<br class="">- DoNothing,<br class="">-<br class="">- /// The argument is treated as if an -autorelease message had been sent to<br class="">- /// the referenced object.<br class="">- Autorelease,<br class="">-<br class="">- /// The argument is treated as if an -dealloc message had been sent to<br class="">- /// the referenced object.<br class="">- Dealloc,<br class="">-<br class="">- /// The argument has its reference count decreased by 1. This is as<br class="">- /// if CFRelease has been called on the argument.<br class="">- DecRef,<br class="">-<br class="">- /// The argument has its reference count decreased by 1. This is as<br class="">- /// if a -release message has been sent to the argument. This differs<br class="">- /// in behavior from DecRef when GC is enabled.<br class="">- DecRefMsg,<br class="">-<br class="">- /// The argument has its reference count decreased by 1 to model<br class="">- /// a transferred bridge cast under ARC.<br class="">- DecRefBridgedTransferred,<br class="">-<br class="">- /// The argument has its reference count increased by 1. This is as<br class="">- /// if a -retain message has been sent to the argument. This differs<br class="">- /// in behavior from IncRef when GC is enabled.<br class="">- IncRefMsg,<br class="">-<br class="">- /// The argument has its reference count increased by 1. This is as<br class="">- /// if CFRetain has been called on the argument.<br class="">- IncRef,<br class="">-<br class="">- /// Used to mark an argument as collectible in GC mode, currently a noop.<br class="">- MakeCollectable,<br class="">-<br class="">- /// The argument is a pointer to a retain-counted object; on exit, the new<br class="">- /// value of the pointer is a +0 value or NULL.<br class="">- UnretainedOutParameter,<br class="">-<br class="">- /// The argument is a pointer to a retain-counted object; on exit, the new<br class="">- /// value of the pointer is a +1 value or NULL.<br class="">- RetainedOutParameter,<br class="">-<br class="">- /// The argument is treated as potentially escaping, meaning that<br class="">- /// even when its reference count hits 0 it should be treated as still<br class="">- /// possibly being alive as someone else *may* be holding onto the object.<br class="">- MayEscape,<br class="">-<br class="">- /// All typestate tracking of the object ceases. This is usually employed<br class="">- /// when the effect of the call is completely unknown.<br class="">- StopTracking,<br class="">-<br class="">- /// All typestate tracking of the object ceases. Unlike StopTracking,<br class="">- /// this is also enforced when the method body is inlined.<br class="">- ///<br class="">- /// In some cases, we obtain a better summary for this checker<br class="">- /// by looking at the call site than by inlining the function.<br class="">- /// Signifies that we should stop tracking the symbol even if<br class="">- /// the function is inlined.<br class="">- StopTrackingHard,<br class="">-<br class="">- /// Performs the combined functionality of DecRef and StopTrackingHard.<br class="">- ///<br class="">- /// The models the effect that the called function decrements the reference<br class="">- /// count of the argument and all typestate tracking on that argument<br class="">- /// should cease.<br class="">- DecRefAndStopTrackingHard,<br class="">-<br class="">- /// Performs the combined functionality of DecRefMsg and StopTrackingHard.<br class="">- ///<br class="">- /// The models the effect that the called function decrements the reference<br class="">- /// count of the argument and all typestate tracking on that argument<br class="">- /// should cease.<br class="">- DecRefMsgAndStopTrackingHard<br class="">-};<br class="">-<br class="">-/// RetEffect summarizes a call's retain/release behavior with respect<br class="">-/// to its return value.<br class="">-class RetEffect {<br class="">-public:<br class="">- enum Kind {<br class="">- /// Indicates that no retain count information is tracked for<br class="">- /// the return value.<br class="">- NoRet,<br class="">- /// Indicates that the returned value is an owned (+1) symbol.<br class="">- OwnedSymbol,<br class="">- /// Indicates that the returned value is an object with retain count<br class="">- /// semantics but that it is not owned (+0). This is the default<br class="">- /// for getters, etc.<br class="">- NotOwnedSymbol,<br class="">- /// Indicates that the object is not owned and controlled by the<br class="">- /// Garbage collector.<br class="">- GCNotOwnedSymbol,<br class="">- /// Indicates that the return value is an owned object when the<br class="">- /// receiver is also a tracked object.<br class="">- OwnedWhenTrackedReceiver,<br class="">- // Treat this function as returning a non-tracked symbol even if<br class="">- // the function has been inlined. This is used where the call<br class="">- // site summary is more presise than the summary indirectly produced<br class="">- // by inlining the function<br class="">- NoRetHard<br class="">- };<br class="">-<br class="">- /// Determines the object kind of a tracked object.<br class="">- enum ObjKind {<br class="">- /// Indicates that the tracked object is a CF object. This is<br class="">- /// important between GC and non-GC code.<br class="">- CF,<br class="">- /// Indicates that the tracked object is an Objective-C object.<br class="">- ObjC,<br class="">- /// Indicates that the tracked object could be a CF or Objective-C object.<br class="">- AnyObj,<br class="">- /// Indicates that the tracked object is a generalized object.<br class="">- Generalized<br class="">- };<br class="">-<br class="">-private:<br class="">- Kind K;<br class="">- ObjKind O;<br class="">-<br class="">- RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}<br class="">-<br class="">-public:<br class="">- Kind getKind() const { return K; }<br class="">-<br class="">- ObjKind getObjKind() const { return O; }<br class="">-<br class="">- bool isOwned() const {<br class="">- return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;<br class="">- }<br class="">-<br class="">- bool notOwned() const {<br class="">- return K == NotOwnedSymbol;<br class="">- }<br class="">-<br class="">- bool operator==(const RetEffect &Other) const {<br class="">- return K == Other.K && O == Other.O;<br class="">- }<br class="">-<br class="">- static RetEffect MakeOwnedWhenTrackedReceiver() {<br class="">- return RetEffect(OwnedWhenTrackedReceiver, ObjC);<br class="">- }<br class="">-<br class="">- static RetEffect MakeOwned(ObjKind o) {<br class="">- return RetEffect(OwnedSymbol, o);<br class="">- }<br class="">- static RetEffect MakeNotOwned(ObjKind o) {<br class="">- return RetEffect(NotOwnedSymbol, o);<br class="">- }<br class="">- static RetEffect MakeGCNotOwned() {<br class="">- return RetEffect(GCNotOwnedSymbol, ObjC);<br class="">- }<br class="">- static RetEffect MakeNoRet() {<br class="">- return RetEffect(NoRet);<br class="">- }<br class="">- static RetEffect MakeNoRetHard() {<br class="">- return RetEffect(NoRetHard);<br class="">- }<br class="">-};<br class="">-<br class="">-/// Encapsulates the retain count semantics on the arguments, return value,<br class="">-/// and receiver (if any) of a function/method call.<br class="">-///<br class="">-/// Note that construction of these objects is not highly efficient. That<br class="">-/// is okay for clients where creating these objects isn't really a bottleneck.<br class="">-/// The purpose of the API is to provide something simple. The actual<br class="">-/// static analyzer checker that implements retain/release typestate<br class="">-/// tracking uses something more efficient.<br class="">-class CallEffects {<br class="">- llvm::SmallVector<ArgEffect, 10> Args;<br class="">- RetEffect Ret;<br class="">- ArgEffect Receiver;<br class="">-<br class="">- CallEffects(const RetEffect &R) : Ret(R) {}<br class="">-<br class="">-public:<br class="">- /// Returns the argument effects for a call.<br class="">- ArrayRef<ArgEffect> getArgs() const { return Args; }<br class="">-<br class="">- /// Returns the effects on the receiver.<br class="">- ArgEffect getReceiver() const { return Receiver; }<br class="">-<br class="">- /// Returns the effect on the return value.<br class="">- RetEffect getReturnValue() const { return Ret; }<br class="">-<br class="">- /// Return the CallEfect for a given Objective-C method.<br class="">- static CallEffects getEffect(const ObjCMethodDecl *MD);<br class="">-<br class="">- /// Return the CallEfect for a given C/C++ function.<br class="">- static CallEffects getEffect(const FunctionDecl *FD);<br class="">-};<br class="">-<br class="">-}}}<br class="">-<br class="">-#endif<br class="">-<br class=""><br class="">Added: cfe/trunk/include/clang/Analysis/RetainSummaryManager.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/RetainSummaryManager.h?rev=340114&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/RetainSummaryManager.h?rev=340114&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/Analysis/RetainSummaryManager.h (added)<br class="">+++ cfe/trunk/include/clang/Analysis/RetainSummaryManager.h Fri Aug 17 18:45:50 2018<br class="">@@ -0,0 +1,706 @@<br class="">+//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+//<br class="">+// This file defines summaries implementation for retain counting, which<br class="">+// implements a reference count checker for Core Foundation and Cocoa<br class="">+// on (Mac OS X).<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER<br class="">+#define LLVM_CLANG_LIB_ANALYSIS_RETAINSUMMARYMANAGER<br class="">+<br class="">+#include "llvm/ADT/DenseMap.h"<br class="">+#include "llvm/ADT/FoldingSet.h"<br class="">+#include "clang/AST/Attr.h"<br class="">+#include "clang/AST/DeclCXX.h"<br class="">+#include "clang/AST/DeclObjC.h"<br class="">+#include "clang/AST/ParentMap.h"<br class="">+#include "clang/StaticAnalyzer/Checkers/SelectorExtras.h"<br class="">+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"<br class="">+#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"<br class="">+#include "clang/StaticAnalyzer/Core/Checker.h"<br class="">+#include "clang/StaticAnalyzer/Core/CheckerManager.h"<br class="">+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"<br class="">+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"<br class="">+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"<br class="">+#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"<br class="">+#include "llvm/ADT/ImmutableList.h"<br class="">+#include "llvm/ADT/ImmutableMap.h"<br class="">+#include "llvm/ADT/STLExtras.h"<br class="">+<br class="">+//===----------------------------------------------------------------------===//<br class="">+// Adapters for FoldingSet.<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+using namespace clang;<br class="">+using namespace ento;<br class="">+<br class="">+namespace clang {<br class="">+namespace ento {<br class="">+<br class="">+/// An ArgEffect summarizes the retain count behavior on an argument or receiver<br class="">+/// to a function or method.<br class="">+enum ArgEffect {<br class="">+ /// There is no effect.<br class="">+ DoNothing,<br class="">+<br class="">+ /// The argument is treated as if an -autorelease message had been sent to<br class="">+ /// the referenced object.<br class="">+ Autorelease,<br class="">+<br class="">+ /// The argument is treated as if an -dealloc message had been sent to<br class="">+ /// the referenced object.<br class="">+ Dealloc,<br class="">+<br class="">+ /// The argument has its reference count decreased by 1. This is as<br class="">+ /// if CFRelease has been called on the argument.<br class="">+ DecRef,<br class="">+<br class="">+ /// The argument has its reference count decreased by 1. This is as<br class="">+ /// if a -release message has been sent to the argument. This differs<br class="">+ /// in behavior from DecRef when GC is enabled.<br class="">+ DecRefMsg,<br class="">+<br class="">+ /// The argument has its reference count decreased by 1 to model<br class="">+ /// a transferred bridge cast under ARC.<br class="">+ DecRefBridgedTransferred,<br class="">+<br class="">+ /// The argument has its reference count increased by 1. This is as<br class="">+ /// if a -retain message has been sent to the argument. This differs<br class="">+ /// in behavior from IncRef when GC is enabled.<br class="">+ IncRefMsg,<br class="">+<br class="">+ /// The argument has its reference count increased by 1. This is as<br class="">+ /// if CFRetain has been called on the argument.<br class="">+ IncRef,<br class="">+<br class="">+ /// The argument acts as if has been passed to CFMakeCollectable, which<br class="">+ /// transfers the object to the Garbage Collector under GC.<br class="">+ MakeCollectable,<br class="">+<br class="">+ /// The argument is a pointer to a retain-counted object; on exit, the new<br class="">+ /// value of the pointer is a +0 value or NULL.<br class="">+ UnretainedOutParameter,<br class="">+<br class="">+ /// The argument is a pointer to a retain-counted object; on exit, the new<br class="">+ /// value of the pointer is a +1 value or NULL.<br class="">+ RetainedOutParameter,<br class="">+<br class="">+ /// The argument is treated as potentially escaping, meaning that<br class="">+ /// even when its reference count hits 0 it should be treated as still<br class="">+ /// possibly being alive as someone else *may* be holding onto the object.<br class="">+ MayEscape,<br class="">+<br class="">+ /// All typestate tracking of the object ceases. This is usually employed<br class="">+ /// when the effect of the call is completely unknown.<br class="">+ StopTracking,<br class="">+<br class="">+ /// All typestate tracking of the object ceases. Unlike StopTracking,<br class="">+ /// this is also enforced when the method body is inlined.<br class="">+ ///<br class="">+ /// In some cases, we obtain a better summary for this checker<br class="">+ /// by looking at the call site than by inlining the function.<br class="">+ /// Signifies that we should stop tracking the symbol even if<br class="">+ /// the function is inlined.<br class="">+ StopTrackingHard,<br class="">+<br class="">+ /// Performs the combined functionality of DecRef and StopTrackingHard.<br class="">+ ///<br class="">+ /// The models the effect that the called function decrements the reference<br class="">+ /// count of the argument and all typestate tracking on that argument<br class="">+ /// should cease.<br class="">+ DecRefAndStopTrackingHard,<br class="">+<br class="">+ /// Performs the combined functionality of DecRefMsg and StopTrackingHard.<br class="">+ ///<br class="">+ /// The models the effect that the called function decrements the reference<br class="">+ /// count of the argument and all typestate tracking on that argument<br class="">+ /// should cease.<br class="">+ DecRefMsgAndStopTrackingHard<br class="">+};<br class="">+<br class="">+/// RetEffect summarizes a call's retain/release behavior with respect<br class="">+/// to its return value.<br class="">+class RetEffect {<br class="">+public:<br class="">+ enum Kind {<br class="">+ /// Indicates that no retain count information is tracked for<br class="">+ /// the return value.<br class="">+ NoRet,<br class="">+ /// Indicates that the returned value is an owned (+1) symbol.<br class="">+ OwnedSymbol,<br class="">+ /// Indicates that the returned value is an object with retain count<br class="">+ /// semantics but that it is not owned (+0). This is the default<br class="">+ /// for getters, etc.<br class="">+ NotOwnedSymbol,<br class="">+ /// Indicates that the object is not owned and controlled by the<br class="">+ /// Garbage collector.<br class="">+ GCNotOwnedSymbol,<br class="">+ /// Indicates that the return value is an owned object when the<br class="">+ /// receiver is also a tracked object.<br class="">+ OwnedWhenTrackedReceiver,<br class="">+ // Treat this function as returning a non-tracked symbol even if<br class="">+ // the function has been inlined. This is used where the call<br class="">+ // site summary is more presise than the summary indirectly produced<br class="">+ // by inlining the function<br class="">+ NoRetHard<br class="">+ };<br class="">+<br class="">+ /// Determines the object kind of a tracked object.<br class="">+ enum ObjKind {<br class="">+ /// Indicates that the tracked object is a CF object. This is<br class="">+ /// important between GC and non-GC code.<br class="">+ CF,<br class="">+ /// Indicates that the tracked object is an Objective-C object.<br class="">+ ObjC,<br class="">+ /// Indicates that the tracked object could be a CF or Objective-C object.<br class="">+ AnyObj,<br class="">+ /// Indicates that the tracked object is a generalized object.<br class="">+ Generalized<br class="">+ };<br class="">+<br class="">+private:<br class="">+ Kind K;<br class="">+ ObjKind O;<br class="">+<br class="">+ RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}<br class="">+<br class="">+public:<br class="">+ Kind getKind() const { return K; }<br class="">+<br class="">+ ObjKind getObjKind() const { return O; }<br class="">+<br class="">+ bool isOwned() const {<br class="">+ return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;<br class="">+ }<br class="">+<br class="">+ bool notOwned() const {<br class="">+ return K == NotOwnedSymbol;<br class="">+ }<br class="">+<br class="">+ bool operator==(const RetEffect &Other) const {<br class="">+ return K == Other.K && O == Other.O;<br class="">+ }<br class="">+<br class="">+ static RetEffect MakeOwnedWhenTrackedReceiver() {<br class="">+ return RetEffect(OwnedWhenTrackedReceiver, ObjC);<br class="">+ }<br class="">+<br class="">+ static RetEffect MakeOwned(ObjKind o) {<br class="">+ return RetEffect(OwnedSymbol, o);<br class="">+ }<br class="">+ static RetEffect MakeNotOwned(ObjKind o) {<br class="">+ return RetEffect(NotOwnedSymbol, o);<br class="">+ }<br class="">+ static RetEffect MakeGCNotOwned() {<br class="">+ return RetEffect(GCNotOwnedSymbol, ObjC);<br class="">+ }<br class="">+ static RetEffect MakeNoRet() {<br class="">+ return RetEffect(NoRet);<br class="">+ }<br class="">+ static RetEffect MakeNoRetHard() {<br class="">+ return RetEffect(NoRetHard);<br class="">+ }<br class="">+};<br class="">+<br class="">+/// Encapsulates the retain count semantics on the arguments, return value,<br class="">+/// and receiver (if any) of a function/method call.<br class="">+///<br class="">+/// Note that construction of these objects is not highly efficient. That<br class="">+/// is okay for clients where creating these objects isn't really a bottleneck.<br class="">+/// The purpose of the API is to provide something simple. The actual<br class="">+/// static analyzer checker that implements retain/release typestate<br class="">+/// tracking uses something more efficient.<br class="">+class CallEffects {<br class="">+ llvm::SmallVector<ArgEffect, 10> Args;<br class="">+ RetEffect Ret;<br class="">+ ArgEffect Receiver;<br class="">+<br class="">+ CallEffects(const RetEffect &R) : Ret(R) {}<br class="">+<br class="">+public:<br class="">+ /// Returns the argument effects for a call.<br class="">+ ArrayRef<ArgEffect> getArgs() const { return Args; }<br class="">+<br class="">+ /// Returns the effects on the receiver.<br class="">+ ArgEffect getReceiver() const { return Receiver; }<br class="">+<br class="">+ /// Returns the effect on the return value.<br class="">+ RetEffect getReturnValue() const { return Ret; }<br class="">+<br class="">+ /// Return the CallEfect for a given Objective-C method.<br class="">+ static CallEffects getEffect(const ObjCMethodDecl *MD);<br class="">+<br class="">+ /// Return the CallEfect for a given C/C++ function.<br class="">+ static CallEffects getEffect(const FunctionDecl *FD);<br class="">+};<br class="">+<br class="">+/// A key identifying a summary.<br class="">+class ObjCSummaryKey {<br class="">+ IdentifierInfo* II;<br class="">+ Selector S;<br class="">+public:<br class="">+ ObjCSummaryKey(IdentifierInfo* ii, Selector s)<br class="">+ : II(ii), S(s) {}<br class="">+<br class="">+ ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)<br class="">+ : II(d ? d->getIdentifier() : nullptr), S(s) {}<br class="">+<br class="">+ ObjCSummaryKey(Selector s)<br class="">+ : II(nullptr), S(s) {}<br class="">+<br class="">+ IdentifierInfo *getIdentifier() const { return II; }<br class="">+ Selector getSelector() const { return S; }<br class="">+};<br class="">+<br class="">+} // end namespace ento<br class="">+} // end namespace clang<br class="">+<br class="">+namespace llvm {<br class="">+<br class="">+template <> struct FoldingSetTrait<ArgEffect> {<br class="">+static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {<br class="">+ ID.AddInteger((unsigned) X);<br class="">+}<br class="">+};<br class="">+template <> struct FoldingSetTrait<RetEffect> {<br class="">+ static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {<br class="">+ ID.AddInteger((unsigned) X.getKind());<br class="">+ ID.AddInteger((unsigned) X.getObjKind());<br class="">+}<br class="">+};<br class="">+<br class="">+template <> struct DenseMapInfo<ObjCSummaryKey> {<br class="">+ static inline ObjCSummaryKey getEmptyKey() {<br class="">+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),<br class="">+ DenseMapInfo<Selector>::getEmptyKey());<br class="">+ }<br class="">+<br class="">+ static inline ObjCSummaryKey getTombstoneKey() {<br class="">+ return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),<br class="">+ DenseMapInfo<Selector>::getTombstoneKey());<br class="">+ }<br class="">+<br class="">+ static unsigned getHashValue(const ObjCSummaryKey &V) {<br class="">+ typedef std::pair<IdentifierInfo*, Selector> PairTy;<br class="">+ return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),<br class="">+ V.getSelector()));<br class="">+ }<br class="">+<br class="">+ static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {<br class="">+ return LHS.getIdentifier() == RHS.getIdentifier() &&<br class="">+ LHS.getSelector() == RHS.getSelector();<br class="">+ }<br class="">+<br class="">+};<br class="">+<br class="">+} // end llvm namespace<br class="">+<br class="">+<br class="">+namespace clang {<br class="">+namespace ento {<br class="">+<br class="">+/// ArgEffects summarizes the effects of a function/method call on all of<br class="">+/// its arguments.<br class="">+typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;<br class="">+<br class="">+/// Summary for a function with respect to ownership changes.<br class="">+class RetainSummary {<br class="">+ /// Args - a map of (index, ArgEffect) pairs, where index<br class="">+ /// specifies the argument (starting from 0). This can be sparsely<br class="">+ /// populated; arguments with no entry in Args use 'DefaultArgEffect'.<br class="">+ ArgEffects Args;<br class="">+<br class="">+ /// DefaultArgEffect - The default ArgEffect to apply to arguments that<br class="">+ /// do not have an entry in Args.<br class="">+ ArgEffect DefaultArgEffect;<br class="">+<br class="">+ /// Receiver - If this summary applies to an Objective-C message expression,<br class="">+ /// this is the effect applied to the state of the receiver.<br class="">+ ArgEffect Receiver;<br class="">+<br class="">+ /// Ret - The effect on the return value. Used to indicate if the<br class="">+ /// function/method call returns a new tracked symbol.<br class="">+ RetEffect Ret;<br class="">+<br class="">+public:<br class="">+ RetainSummary(ArgEffects A, RetEffect R, ArgEffect defaultEff,<br class="">+ ArgEffect ReceiverEff)<br class="">+ : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}<br class="">+<br class="">+ /// getArg - Return the argument effect on the argument specified by<br class="">+ /// idx (starting from 0).<br class="">+ ArgEffect getArg(unsigned idx) const {<br class="">+ if (const ArgEffect *AE = Args.lookup(idx))<br class="">+ return *AE;<br class="">+<br class="">+ return DefaultArgEffect;<br class="">+ }<br class="">+<br class="">+ void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {<br class="">+ Args = af.add(Args, idx, e);<br class="">+ }<br class="">+<br class="">+ /// setDefaultArgEffect - Set the default argument effect.<br class="">+ void setDefaultArgEffect(ArgEffect E) {<br class="">+ DefaultArgEffect = E;<br class="">+ }<br class="">+<br class="">+ /// getRetEffect - Returns the effect on the return value of the call.<br class="">+ RetEffect getRetEffect() const { return Ret; }<br class="">+<br class="">+ /// setRetEffect - Set the effect of the return value of the call.<br class="">+ void setRetEffect(RetEffect E) { Ret = E; }<br class="">+<br class="">+<br class="">+ /// Sets the effect on the receiver of the message.<br class="">+ void setReceiverEffect(ArgEffect e) { Receiver = e; }<br class="">+<br class="">+ /// getReceiverEffect - Returns the effect on the receiver of the call.<br class="">+ /// This is only meaningful if the summary applies to an ObjCMessageExpr*.<br class="">+ ArgEffect getReceiverEffect() const { return Receiver; }<br class="">+<br class="">+ /// Test if two retain summaries are identical. Note that merely equivalent<br class="">+ /// summaries are not necessarily identical (for example, if an explicit<br class="">+ /// argument effect matches the default effect).<br class="">+ bool operator==(const RetainSummary &Other) const {<br class="">+ return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&<br class="">+ Receiver == Other.Receiver && Ret == Other.Ret;<br class="">+ }<br class="">+<br class="">+ /// Profile this summary for inclusion in a FoldingSet.<br class="">+ void Profile(llvm::FoldingSetNodeID& ID) const {<br class="">+ ID.Add(Args);<br class="">+ ID.Add(DefaultArgEffect);<br class="">+ ID.Add(Receiver);<br class="">+ ID.Add(Ret);<br class="">+ }<br class="">+<br class="">+ /// A retain summary is simple if it has no ArgEffects other than the default.<br class="">+ bool isSimple() const {<br class="">+ return Args.isEmpty();<br class="">+ }<br class="">+<br class="">+ ArgEffects getArgEffects() const { return Args; }<br class="">+<br class="">+private:<br class="">+ ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }<br class="">+<br class="">+ friend class RetainSummaryManager;<br class="">+};<br class="">+<br class="">+class ObjCSummaryCache {<br class="">+ typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;<br class="">+ MapTy M;<br class="">+public:<br class="">+ ObjCSummaryCache() {}<br class="">+<br class="">+ const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {<br class="">+ // Do a lookup with the (D,S) pair. If we find a match return<br class="">+ // the iterator.<br class="">+ ObjCSummaryKey K(D, S);<br class="">+ MapTy::iterator I = M.find(K);<br class="">+<br class="">+ if (I != M.end())<br class="">+ return I->second;<br class="">+ if (!D)<br class="">+ return nullptr;<br class="">+<br class="">+ // Walk the super chain. If we find a hit with a parent, we'll end<br class="">+ // up returning that summary. We actually allow that key (null,S), as<br class="">+ // we cache summaries for the null ObjCInterfaceDecl* to allow us to<br class="">+ // generate initial summaries without having to worry about NSObject<br class="">+ // being declared.<br class="">+ // FIXME: We may change this at some point.<br class="">+ for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {<br class="">+ if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())<br class="">+ break;<br class="">+<br class="">+ if (!C)<br class="">+ return nullptr;<br class="">+ }<br class="">+<br class="">+ // Cache the summary with original key to make the next lookup faster<br class="">+ // and return the iterator.<br class="">+ const RetainSummary *Summ = I->second;<br class="">+ M[K] = Summ;<br class="">+ return Summ;<br class="">+ }<br class="">+<br class="">+ const RetainSummary *find(IdentifierInfo* II, Selector S) {<br class="">+ // FIXME: Class method lookup. Right now we don't have a good way<br class="">+ // of going between IdentifierInfo* and the class hierarchy.<br class="">+ MapTy::iterator I = M.find(ObjCSummaryKey(II, S));<br class="">+<br class="">+ if (I == M.end())<br class="">+ I = M.find(ObjCSummaryKey(S));<br class="">+<br class="">+ return I == M.end() ? nullptr : I->second;<br class="">+ }<br class="">+<br class="">+ const RetainSummary *& operator[](ObjCSummaryKey K) {<br class="">+ return M[K];<br class="">+ }<br class="">+<br class="">+ const RetainSummary *& operator[](Selector S) {<br class="">+ return M[ ObjCSummaryKey(S) ];<br class="">+ }<br class="">+};<br class="">+<br class="">+class RetainSummaryManager {<br class="">+ typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *><br class="">+ FuncSummariesTy;<br class="">+<br class="">+ typedef ObjCSummaryCache ObjCMethodSummariesTy;<br class="">+<br class="">+ typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;<br class="">+<br class="">+ /// Ctx - The ASTContext object for the analyzed ASTs.<br class="">+ ASTContext &Ctx;<br class="">+<br class="">+ /// Records whether or not the analyzed code runs in ARC mode.<br class="">+ const bool ARCEnabled;<br class="">+<br class="">+ /// FuncSummaries - A map from FunctionDecls to summaries.<br class="">+ FuncSummariesTy FuncSummaries;<br class="">+<br class="">+ /// ObjCClassMethodSummaries - A map from selectors (for instance methods)<br class="">+ /// to summaries.<br class="">+ ObjCMethodSummariesTy ObjCClassMethodSummaries;<br class="">+<br class="">+ /// ObjCMethodSummaries - A map from selectors to summaries.<br class="">+ ObjCMethodSummariesTy ObjCMethodSummaries;<br class="">+<br class="">+ /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,<br class="">+ /// and all other data used by the checker.<br class="">+ llvm::BumpPtrAllocator BPAlloc;<br class="">+<br class="">+ /// AF - A factory for ArgEffects objects.<br class="">+ ArgEffects::Factory AF;<br class="">+<br class="">+ /// ScratchArgs - A holding buffer for construct ArgEffects.<br class="">+ ArgEffects ScratchArgs;<br class="">+<br class="">+ /// ObjCAllocRetE - Default return effect for methods returning Objective-C<br class="">+ /// objects.<br class="">+ RetEffect ObjCAllocRetE;<br class="">+<br class="">+ /// ObjCInitRetE - Default return effect for init methods returning<br class="">+ /// Objective-C objects.<br class="">+ RetEffect ObjCInitRetE;<br class="">+<br class="">+ /// SimpleSummaries - Used for uniquing summaries that don't have special<br class="">+ /// effects.<br class="">+ llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;<br class="">+<br class="">+ /// getArgEffects - Returns a persistent ArgEffects object based on the<br class="">+ /// data in ScratchArgs.<br class="">+ ArgEffects getArgEffects();<br class="">+<br class="">+ enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };<br class="">+<br class="">+ const RetainSummary *getUnarySummary(const FunctionType* FT,<br class="">+ UnaryFuncKind func);<br class="">+<br class="">+ const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);<br class="">+ const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);<br class="">+ const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);<br class="">+<br class="">+ const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);<br class="">+<br class="">+ const RetainSummary *getPersistentSummary(RetEffect RetEff,<br class="">+ ArgEffect ReceiverEff = DoNothing,<br class="">+ ArgEffect DefaultEff = MayEscape) {<br class="">+ RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);<br class="">+ return getPersistentSummary(Summ);<br class="">+ }<br class="">+<br class="">+ const RetainSummary *getDoNothingSummary() {<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ }<br class="">+<br class="">+ const RetainSummary *getDefaultSummary() {<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(),<br class="">+ DoNothing, MayEscape);<br class="">+ }<br class="">+<br class="">+ const RetainSummary *getPersistentStopSummary() {<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(),<br class="">+ StopTracking, StopTracking);<br class="">+ }<br class="">+<br class="">+ void InitializeClassMethodSummaries();<br class="">+ void InitializeMethodSummaries();<br class="">+<br class="">+ void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {<br class="">+ ObjCClassMethodSummaries[S] = Summ;<br class="">+ }<br class="">+<br class="">+ void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {<br class="">+ ObjCMethodSummaries[S] = Summ;<br class="">+ }<br class="">+<br class="">+ void addClassMethSummary(const char* Cls, const char* name,<br class="">+ const RetainSummary *Summ, bool isNullary = true) {<br class="">+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);<br class="">+ Selector S = isNullary ? GetNullarySelector(name, Ctx)<br class="">+ : GetUnarySelector(name, Ctx);<br class="">+ ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;<br class="">+ }<br class="">+<br class="">+ void addInstMethSummary(const char* Cls, const char* nullaryName,<br class="">+ const RetainSummary *Summ) {<br class="">+ IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);<br class="">+ Selector S = GetNullarySelector(nullaryName, Ctx);<br class="">+ ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;<br class="">+ }<br class="">+<br class="">+ template <typename... Keywords><br class="">+ void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,<br class="">+ const RetainSummary *Summ, Keywords *... Kws) {<br class="">+ Selector S = getKeywordSelector(Ctx, Kws...);<br class="">+ Summaries[ObjCSummaryKey(ClsII, S)] = Summ;<br class="">+ }<br class="">+<br class="">+ template <typename... Keywords><br class="">+ void addInstMethSummary(const char *Cls, const RetainSummary *Summ,<br class="">+ Keywords *... Kws) {<br class="">+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);<br class="">+ }<br class="">+<br class="">+ template <typename... Keywords><br class="">+ void addClsMethSummary(const char *Cls, const RetainSummary *Summ,<br class="">+ Keywords *... Kws) {<br class="">+ addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,<br class="">+ Kws...);<br class="">+ }<br class="">+<br class="">+ template <typename... Keywords><br class="">+ void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,<br class="">+ Keywords *... Kws) {<br class="">+ addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);<br class="">+ }<br class="">+<br class="">+ const RetainSummary * generateSummary(const FunctionDecl *FD,<br class="">+ bool &AllowAnnotations);<br class="">+<br class="">+public:<br class="">+ RetainSummaryManager(ASTContext &ctx, bool usesARC)<br class="">+ : Ctx(ctx),<br class="">+ ARCEnabled(usesARC),<br class="">+ AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),<br class="">+ ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)<br class="">+ : RetEffect::MakeOwned(RetEffect::ObjC)),<br class="">+ ObjCInitRetE(usesARC ? RetEffect::MakeNotOwned(RetEffect::ObjC)<br class="">+ : RetEffect::MakeOwnedWhenTrackedReceiver()) {<br class="">+ InitializeClassMethodSummaries();<br class="">+ InitializeMethodSummaries();<br class="">+ }<br class="">+<br class="">+ bool canEval(const CallExpr *CE,<br class="">+ const FunctionDecl *FD,<br class="">+ bool &hasTrustedImplementationAnnotation);<br class="">+<br class="">+ bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);<br class="">+<br class="">+ const RetainSummary *getSummary(const CallEvent &Call,<br class="">+ QualType ReceiverType=QualType());<br class="">+<br class="">+ const RetainSummary *getFunctionSummary(const FunctionDecl *FD);<br class="">+<br class="">+ const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,<br class="">+ const ObjCMethodDecl *MD,<br class="">+ QualType RetTy,<br class="">+ ObjCMethodSummariesTy &CachedSummaries);<br class="">+<br class="">+ const RetainSummary *<br class="">+ getInstanceMethodSummary(const ObjCMethodCall &M,<br class="">+ QualType ReceiverType);<br class="">+<br class="">+ const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {<br class="">+ assert(!M.isInstanceMessage());<br class="">+ const ObjCInterfaceDecl *Class = M.getReceiverInterface();<br class="">+<br class="">+ return getMethodSummary(M.getSelector(), Class, M.getDecl(),<br class="">+ M.getResultType(), ObjCClassMethodSummaries);<br class="">+ }<br class="">+<br class="">+ /// getMethodSummary - This version of getMethodSummary is used to query<br class="">+ /// the summary for the current method being analyzed.<br class="">+ const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {<br class="">+ const ObjCInterfaceDecl *ID = MD->getClassInterface();<br class="">+ Selector S = MD->getSelector();<br class="">+ QualType ResultTy = MD->getReturnType();<br class="">+<br class="">+ ObjCMethodSummariesTy *CachedSummaries;<br class="">+ if (MD->isInstanceMethod())<br class="">+ CachedSummaries = &ObjCMethodSummaries;<br class="">+ else<br class="">+ CachedSummaries = &ObjCClassMethodSummaries;<br class="">+<br class="">+ return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);<br class="">+ }<br class="">+<br class="">+ const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,<br class="">+ Selector S, QualType RetTy);<br class="">+<br class="">+ /// Determine if there is a special return effect for this function or method.<br class="">+ Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,<br class="">+ const Decl *D);<br class="">+<br class="">+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,<br class="">+ const ObjCMethodDecl *MD);<br class="">+<br class="">+ void updateSummaryFromAnnotations(const RetainSummary *&Summ,<br class="">+ const FunctionDecl *FD);<br class="">+<br class="">+ void updateSummaryForCall(const RetainSummary *&Summ,<br class="">+ const CallEvent &Call);<br class="">+<br class="">+ bool isARCEnabled() const { return ARCEnabled; }<br class="">+<br class="">+ RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }<br class="">+<br class="">+ friend class RetainSummaryTemplate;<br class="">+};<br class="">+<br class="">+// Used to avoid allocating long-term (BPAlloc'd) memory for default retain<br class="">+// summaries. If a function or method looks like it has a default summary, but<br class="">+// it has annotations, the annotations are added to the stack-based template<br class="">+// and then copied into managed memory.<br class="">+class RetainSummaryTemplate {<br class="">+ RetainSummaryManager &Manager;<br class="">+ const RetainSummary *&RealSummary;<br class="">+ RetainSummary ScratchSummary;<br class="">+ bool Accessed;<br class="">+public:<br class="">+ RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)<br class="">+ : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}<br class="">+<br class="">+ ~RetainSummaryTemplate() {<br class="">+ if (Accessed)<br class="">+ RealSummary = Manager.getPersistentSummary(ScratchSummary);<br class="">+ }<br class="">+<br class="">+ RetainSummary &operator*() {<br class="">+ Accessed = true;<br class="">+ return ScratchSummary;<br class="">+ }<br class="">+<br class="">+ RetainSummary *operator->() {<br class="">+ Accessed = true;<br class="">+ return &ScratchSummary;<br class="">+ }<br class="">+};<br class="">+<br class="">+} // end namespace ento<br class="">+} // end namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Added: cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h?rev=340114&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h?rev=340114&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h (added)<br class="">+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/SelectorExtras.h Fri Aug 17 18:45:50 2018<br class="">@@ -0,0 +1,39 @@<br class="">+//=== SelectorExtras.h - Helpers for checkers using selectors -----*- C++ -*-=//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H<br class="">+#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_SELECTOREXTRAS_H<br class="">+<br class="">+#include "clang/AST/ASTContext.h"<br class="">+<br class="">+namespace clang {<br class="">+namespace ento {<br class="">+<br class="">+template <typename... IdentifierInfos><br class="">+static inline Selector getKeywordSelector(ASTContext &Ctx,<br class="">+ IdentifierInfos *... IIs) {<br class="">+ static_assert(sizeof...(IdentifierInfos),<br class="">+ "keyword selectors must have at least one argument");<br class="">+ SmallVector<IdentifierInfo *, 10> II({&Ctx.Idents.get(IIs)...});<br class="">+<br class="">+ return Ctx.Selectors.getSelector(II.size(), &II[0]);<br class="">+}<br class="">+<br class="">+template <typename... IdentifierInfos><br class="">+static inline void lazyInitKeywordSelector(Selector &Sel, ASTContext &Ctx,<br class="">+ IdentifierInfos *... IIs) {<br class="">+ if (!Sel.isNull())<br class="">+ return;<br class="">+ Sel = getKeywordSelector(Ctx, IIs...);<br class="">+}<br class="">+<br class="">+} // end namespace ento<br class="">+} // end namespace clang<br class="">+<br class="">+#endif<br class=""><br class="">Modified: cfe/trunk/lib/ARCMigrate/CMakeLists.txt<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/CMakeLists.txt?rev=340114&r1=340113&r2=340114&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/CMakeLists.txt?rev=340114&r1=340113&r2=340114&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/ARCMigrate/CMakeLists.txt (original)<br class="">+++ cfe/trunk/lib/ARCMigrate/CMakeLists.txt Fri Aug 17 18:45:50 2018<br class="">@@ -34,5 +34,4 @@ add_clang_library(clangARCMigrate<br class=""> clangRewrite<br class=""> clangSema<br class=""> clangSerialization<br class="">- clangStaticAnalyzerCheckers<br class=""> )<br class=""><br class="">Modified: cfe/trunk/lib/ARCMigrate/ObjCMT.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=340114&r1=340113&r2=340114&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=340114&r1=340113&r2=340114&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/ARCMigrate/ObjCMT.cpp (original)<br class="">+++ cfe/trunk/lib/ARCMigrate/ObjCMT.cpp Fri Aug 17 18:45:50 2018<br class="">@@ -8,7 +8,7 @@<br class="">//===----------------------------------------------------------------------===//<br class=""><br class="">#include "Transforms.h"<br class="">-#include "clang/Analysis/ObjCRetainCount.h"<br class="">+#include "clang/Analysis/RetainSummaryManager.h"<br class="">#include "clang/ARCMigrate/ARCMT.h"<br class="">#include "clang/ARCMigrate/ARCMTActions.h"<br class="">#include "clang/AST/ASTConsumer.h"<br class="">@@ -35,8 +35,8 @@<br class="">#include "llvm/Support/YAMLParser.h"<br class=""><br class="">using namespace clang;<br class="">+using namespace ento;<br class="">using namespace arcmt;<br class="">-using namespace ento::objc_retain;<br class=""><br class="">namespace {<br class=""><br class=""><br class="">Modified: cfe/trunk/lib/Analysis/CMakeLists.txt<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=340114&r1=340113&r2=340114&view=diff" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=340114&r1=340113&r2=340114&view=diff</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)<br class="">+++ cfe/trunk/lib/Analysis/CMakeLists.txt Fri Aug 17 18:45:50 2018<br class="">@@ -24,6 +24,7 @@ add_clang_library(clangAnalysis<br class=""> ProgramPoint.cpp<br class=""> PseudoConstantAnalysis.cpp<br class=""> ReachableCode.cpp<br class="">+ RetainSummaryManager.cpp<br class=""> ScanfFormatString.cpp<br class=""> ThreadSafety.cpp<br class=""> ThreadSafetyCommon.cpp<br class=""><br class="">Added: cfe/trunk/lib/Analysis/RetainSummaryManager.cpp<br class="">URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RetainSummaryManager.cpp?rev=340114&view=auto" class="">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RetainSummaryManager.cpp?rev=340114&view=auto</a><br class="">==============================================================================<br class="">--- cfe/trunk/lib/Analysis/RetainSummaryManager.cpp (added)<br class="">+++ cfe/trunk/lib/Analysis/RetainSummaryManager.cpp Fri Aug 17 18:45:50 2018<br class="">@@ -0,0 +1,902 @@<br class="">+//== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--//<br class="">+//<br class="">+// The LLVM Compiler Infrastructure<br class="">+//<br class="">+// This file is distributed under the University of Illinois Open Source<br class="">+// License. See LICENSE.TXT for details.<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+//<br class="">+// This file defines summaries implementation for retain counting, which<br class="">+// implements a reference count checker for Core Foundation and Cocoa<br class="">+// on (Mac OS X).<br class="">+//<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+#include "clang/Analysis/RetainSummaryManager.h"<br class="">+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"<br class="">+#include "clang/AST/Attr.h"<br class="">+#include "clang/AST/DeclCXX.h"<br class="">+#include "clang/AST/DeclObjC.h"<br class="">+#include "clang/AST/ParentMap.h"<br class="">+<br class="">+using namespace clang;<br class="">+using namespace ento;<br class="">+<br class="">+ArgEffects RetainSummaryManager::getArgEffects() {<br class="">+ ArgEffects AE = ScratchArgs;<br class="">+ ScratchArgs = AF.getEmptyMap();<br class="">+ return AE;<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {<br class="">+ // Unique "simple" summaries -- those without ArgEffects.<br class="">+ if (OldSumm.isSimple()) {<br class="">+ ::llvm::FoldingSetNodeID ID;<br class="">+ OldSumm.Profile(ID);<br class="">+<br class="">+ void *Pos;<br class="">+ CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);<br class="">+<br class="">+ if (!N) {<br class="">+ N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();<br class="">+ new (N) CachedSummaryNode(OldSumm);<br class="">+ SimpleSummaries.InsertNode(N, Pos);<br class="">+ }<br class="">+<br class="">+ return &N->getValue();<br class="">+ }<br class="">+<br class="">+ RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();<br class="">+ new (Summ) RetainSummary(OldSumm);<br class="">+ return Summ;<br class="">+}<br class="">+<br class="">+static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {<br class="">+ for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {<br class="">+ if (Ann->getAnnotation() == rcAnnotation)<br class="">+ return true;<br class="">+ }<br class="">+ return false;<br class="">+}<br class="">+<br class="">+static bool isRetain(const FunctionDecl *FD, StringRef FName) {<br class="">+ return FName.startswith_lower("retain") || FName.endswith_lower("retain");<br class="">+}<br class="">+<br class="">+static bool isRelease(const FunctionDecl *FD, StringRef FName) {<br class="">+ return FName.startswith_lower("release") || FName.endswith_lower("release");<br class="">+}<br class="">+<br class="">+static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {<br class="">+ return FName.startswith_lower("autorelease") ||<br class="">+ FName.endswith_lower("autorelease");<br class="">+}<br class="">+<br class="">+static bool isMakeCollectable(StringRef FName) {<br class="">+ return FName.contains_lower("MakeCollectable");<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::generateSummary(const FunctionDecl *FD,<br class="">+ bool &AllowAnnotations) {<br class="">+ // We generate "stop" summaries for implicitly defined functions.<br class="">+ if (FD->isImplicit()) {<br class="">+ return getPersistentStopSummary();<br class="">+ }<br class="">+<br class="">+ // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the<br class="">+ // function's type.<br class="">+ const FunctionType *FT = FD->getType()->getAs<FunctionType>();<br class="">+ const IdentifierInfo *II = FD->getIdentifier();<br class="">+ if (!II)<br class="">+ return getDefaultSummary();<br class="">+<br class="">+ StringRef FName = II->getName();<br class="">+<br class="">+ // Strip away preceding '_'. Doing this here will effect all the checks<br class="">+ // down below.<br class="">+ FName = FName.substr(FName.find_first_not_of('_'));<br class="">+<br class="">+ // Inspect the result type.<br class="">+ QualType RetTy = FT->getReturnType();<br class="">+ std::string RetTyName = RetTy.getAsString();<br class="">+<br class="">+ // FIXME: This should all be refactored into a chain of "summary lookup"<br class="">+ // filters.<br class="">+ assert(ScratchArgs.isEmpty());<br class="">+<br class="">+ if (FName == "pthread_create" || FName == "pthread_setspecific") {<br class="">+ // Part of: <<a href="rdar://problem/7299394" class="">rdar://problem/7299394</a>> and <<a href="rdar://problem/11282706" class="">rdar://problem/11282706</a>>.<br class="">+ // This will be addressed better with IPA.<br class="">+ return getPersistentStopSummary();<br class="">+ } else if(FName == "NSMakeCollectable") {<br class="">+ // Handle: id NSMakeCollectable(CFTypeRef)<br class="">+ AllowAnnotations = false;<br class="">+ return RetTy->isObjCIdType() ? getUnarySummary(FT, cfmakecollectable)<br class="">+ : getPersistentStopSummary();<br class="">+ } else if (FName == "CFPlugInInstanceCreate") {<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet());<br class="">+ } else if (FName == "IORegistryEntrySearchCFProperty" ||<br class="">+ (RetTyName == "CFMutableDictionaryRef" &&<br class="">+ (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||<br class="">+ FName == "IOServiceNameMatching" ||<br class="">+ FName == "IORegistryEntryIDMatching" ||<br class="">+ FName == "IOOpenFirmwarePathMatching"))) {<br class="">+ // Part of <<a href="rdar://problem/6961230" class="">rdar://problem/6961230</a>>. (IOKit)<br class="">+ // This should be addressed using a API table.<br class="">+ return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing,<br class="">+ DoNothing);<br class="">+ } else if (FName == "IOServiceGetMatchingService" ||<br class="">+ FName == "IOServiceGetMatchingServices") {<br class="">+ // FIXES: <<a href="rdar://problem/6326900" class="">rdar://problem/6326900</a>><br class="">+ // This should be addressed using a API table. This strcmp is also<br class="">+ // a little gross, but there is no need to super optimize here.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 1, DecRef);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName == "IOServiceAddNotification" ||<br class="">+ FName == "IOServiceAddMatchingNotification") {<br class="">+ // Part of <<a href="rdar://problem/6961230" class="">rdar://problem/6961230</a>>. (IOKit)<br class="">+ // This should be addressed using a API table.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 2, DecRef);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName == "CVPixelBufferCreateWithBytes") {<br class="">+ // FIXES: <<a href="rdar://problem/7283567" class="">rdar://problem/7283567</a>><br class="">+ // Eventually this can be improved by recognizing that the pixel<br class="">+ // buffer passed to CVPixelBufferCreateWithBytes is released via<br class="">+ // a callback and doing full IPA to make sure this is done correctly.<br class="">+ // FIXME: This function has an out parameter that returns an<br class="">+ // allocated object.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName == "CGBitmapContextCreateWithData") {<br class="">+ // FIXES: <<a href="rdar://problem/7358899" class="">rdar://problem/7358899</a>><br class="">+ // Eventually this can be improved by recognizing that 'releaseInfo'<br class="">+ // passed to CGBitmapContextCreateWithData is released via<br class="">+ // a callback and doing full IPA to make sure this is done correctly.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing,<br class="">+ DoNothing);<br class="">+ } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {<br class="">+ // FIXES: <<a href="rdar://problem/7283567" class="">rdar://problem/7283567</a>><br class="">+ // Eventually this can be improved by recognizing that the pixel<br class="">+ // buffer passed to CVPixelBufferCreateWithPlanarBytes is released<br class="">+ // via a callback and doing full IPA to make sure this is done<br class="">+ // correctly.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName == "VTCompressionSessionEncodeFrame") {<br class="">+ // The context argument passed to VTCompressionSessionEncodeFrame()<br class="">+ // is passed to the callback specified when creating the session<br class="">+ // (e.g. with VTCompressionSessionCreate()) which can release it.<br class="">+ // To account for this possibility, conservatively stop tracking<br class="">+ // the context.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName == "dispatch_set_context" ||<br class="">+ FName == "xpc_connection_set_context") {<br class="">+ // <<a href="rdar://problem/11059275" class="">rdar://problem/11059275</a>> - The analyzer currently doesn't have<br class="">+ // a good way to reason about the finalizer function for libdispatch.<br class="">+ // If we pass a context object that is memory managed, stop tracking it.<br class="">+ // <<a href="rdar://problem/13783514" class="">rdar://problem/13783514</a>> - Same problem, but for XPC.<br class="">+ // FIXME: this hack should possibly go away once we can handle<br class="">+ // libdispatch and XPC finalizers.<br class="">+ ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ } else if (FName.startswith("NSLog")) {<br class="">+ return getDoNothingSummary();<br class="">+ } else if (FName.startswith("NS") &&<br class="">+ (FName.find("Insert") != StringRef::npos)) {<br class="">+ // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can<br class="">+ // be deallocated by NSMapRemove. (<a href="radar://11152419" class="">radar://11152419</a>)<br class="">+ ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);<br class="">+ ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+ }<br class="">+<br class="">+ if (RetTy->isPointerType()) {<br class="">+ // For CoreFoundation ('CF') types.<br class="">+ if (cocoa::isRefType(RetTy, "CF", FName)) {<br class="">+ if (isRetain(FD, FName)) {<br class="">+ // CFRetain isn't supposed to be annotated. However, this may as well<br class="">+ // be a user-made "safe" CFRetain function that is incorrectly<br class="">+ // annotated as cf_returns_retained due to lack of better options.<br class="">+ // We want to ignore such annotation.<br class="">+ AllowAnnotations = false;<br class="">+<br class="">+ return getUnarySummary(FT, cfretain);<br class="">+ } else if (isAutorelease(FD, FName)) {<br class="">+ // The headers use cf_consumed, but we can fully model CFAutorelease<br class="">+ // ourselves.<br class="">+ AllowAnnotations = false;<br class="">+<br class="">+ return getUnarySummary(FT, cfautorelease);<br class="">+ } else if (isMakeCollectable(FName)) {<br class="">+ AllowAnnotations = false;<br class="">+ return getUnarySummary(FT, cfmakecollectable);<br class="">+ } else {<br class="">+ return getCFCreateGetRuleSummary(FD);<br class="">+ }<br class="">+ }<br class="">+<br class="">+ // For CoreGraphics ('CG') and CoreVideo ('CV') types.<br class="">+ if (cocoa::isRefType(RetTy, "CG", FName) ||<br class="">+ cocoa::isRefType(RetTy, "CV", FName)) {<br class="">+ if (isRetain(FD, FName))<br class="">+ return getUnarySummary(FT, cfretain);<br class="">+ else<br class="">+ return getCFCreateGetRuleSummary(FD);<br class="">+ }<br class="">+<br class="">+ // For all other CF-style types, use the Create/Get<br class="">+ // rule for summaries but don't support Retain functions<br class="">+ // with framework-specific prefixes.<br class="">+ if (coreFoundation::isCFObjectRef(RetTy)) {<br class="">+ return getCFCreateGetRuleSummary(FD);<br class="">+ }<br class="">+<br class="">+ if (FD->hasAttr<CFAuditedTransferAttr>()) {<br class="">+ return getCFCreateGetRuleSummary(FD);<br class="">+ }<br class="">+ }<br class="">+<br class="">+ // Check for release functions, the only kind of functions that we care<br class="">+ // about that don't return a pointer type.<br class="">+ if (FName.size() >= 2 && FName[0] == 'C' &&<br class="">+ (FName[1] == 'F' || FName[1] == 'G')) {<br class="">+ // Test for 'CGCF'.<br class="">+ FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);<br class="">+<br class="">+ if (isRelease(FD, FName))<br class="">+ return getUnarySummary(FT, cfrelease);<br class="">+ else {<br class="">+ assert(ScratchArgs.isEmpty());<br class="">+ // Remaining CoreFoundation and CoreGraphics functions.<br class="">+ // We use to assume that they all strictly followed the ownership idiom<br class="">+ // and that ownership cannot be transferred. While this is technically<br class="">+ // correct, many methods allow a tracked object to escape. For example:<br class="">+ //<br class="">+ // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);<br class="">+ // CFDictionaryAddValue(y, key, x);<br class="">+ // CFRelease(x);<br class="">+ // ... it is okay to use 'x' since 'y' has a reference to it<br class="">+ //<br class="">+ // We handle this and similar cases with the follow heuristic. If the<br class="">+ // function name contains "InsertValue", "SetValue", "AddValue",<br class="">+ // "AppendValue", or "SetAttribute", then we assume that arguments may<br class="">+ // "escape." This means that something else holds on to the object,<br class="">+ // allowing it be used even after its local retain count drops to 0.<br class="">+ ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||<br class="">+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||<br class="">+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||<br class="">+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||<br class="">+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)<br class="">+ ? MayEscape<br class="">+ : DoNothing;<br class="">+<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);<br class="">+ }<br class="">+ }<br class="">+<br class="">+ return getDefaultSummary();<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {<br class="">+ // If we don't know what function we're calling, use our default summary.<br class="">+ if (!FD)<br class="">+ return getDefaultSummary();<br class="">+<br class="">+ // Look up a summary in our cache of FunctionDecls -> Summaries.<br class="">+ FuncSummariesTy::iterator I = FuncSummaries.find(FD);<br class="">+ if (I != FuncSummaries.end())<br class="">+ return I->second;<br class="">+<br class="">+ // No summary? Generate one.<br class="">+ bool AllowAnnotations = true;<br class="">+ const RetainSummary *S = generateSummary(FD, AllowAnnotations);<br class="">+<br class="">+ // Annotations override defaults.<br class="">+ if (AllowAnnotations)<br class="">+ updateSummaryFromAnnotations(S, FD);<br class="">+<br class="">+ FuncSummaries[FD] = S;<br class="">+ return S;<br class="">+}<br class="">+<br class="">+//===----------------------------------------------------------------------===//<br class="">+// Summary creation for functions (largely uses of Core Foundation).<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {<br class="">+ switch (E) {<br class="">+ case DoNothing:<br class="">+ case Autorelease:<br class="">+ case DecRefBridgedTransferred:<br class="">+ case IncRef:<br class="">+ case IncRefMsg:<br class="">+ case MakeCollectable:<br class="">+ case UnretainedOutParameter:<br class="">+ case RetainedOutParameter:<br class="">+ case MayEscape:<br class="">+ case StopTracking:<br class="">+ case StopTrackingHard:<br class="">+ return StopTrackingHard;<br class="">+ case DecRef:<br class="">+ case DecRefAndStopTrackingHard:<br class="">+ return DecRefAndStopTrackingHard;<br class="">+ case DecRefMsg:<br class="">+ case DecRefMsgAndStopTrackingHard:<br class="">+ return DecRefMsgAndStopTrackingHard;<br class="">+ case Dealloc:<br class="">+ return Dealloc;<br class="">+ }<br class="">+<br class="">+ llvm_unreachable("Unknown ArgEffect kind");<br class="">+}<br class="">+<br class="">+void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,<br class="">+ const CallEvent &Call) {<br class="">+ if (Call.hasNonZeroCallbackArg()) {<br class="">+ ArgEffect RecEffect =<br class="">+ getStopTrackingHardEquivalent(S->getReceiverEffect());<br class="">+ ArgEffect DefEffect =<br class="">+ getStopTrackingHardEquivalent(S->getDefaultArgEffect());<br class="">+<br class="">+ ArgEffects CustomArgEffects = S->getArgEffects();<br class="">+ for (ArgEffects::iterator I = CustomArgEffects.begin(),<br class="">+ E = CustomArgEffects.end();<br class="">+ I != E; ++I) {<br class="">+ ArgEffect Translated = getStopTrackingHardEquivalent(I->second);<br class="">+ if (Translated != DefEffect)<br class="">+ ScratchArgs = AF.add(ScratchArgs, I->first, Translated);<br class="">+ }<br class="">+<br class="">+ RetEffect RE = RetEffect::MakeNoRetHard();<br class="">+<br class="">+ // Special cases where the callback argument CANNOT free the return value.<br class="">+ // This can generally only happen if we know that the callback will only be<br class="">+ // called when the return value is already being deallocated.<br class="">+ if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {<br class="">+ if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {<br class="">+ // When the CGBitmapContext is deallocated, the callback here will free<br class="">+ // the associated data buffer.<br class="">+ // The callback in dispatch_data_create frees the buffer, but not<br class="">+ // the data object.<br class="">+ if (Name->isStr("CGBitmapContextCreateWithData") ||<br class="">+ Name->isStr("dispatch_data_create"))<br class="">+ RE = S->getRetEffect();<br class="">+ }<br class="">+ }<br class="">+<br class="">+ S = getPersistentSummary(RE, RecEffect, DefEffect);<br class="">+ }<br class="">+<br class="">+ // Special case '[super init];' and '[self init];'<br class="">+ //<br class="">+ // Even though calling '[super init]' without assigning the result to self<br class="">+ // and checking if the parent returns 'nil' is a bad pattern, it is common.<br class="">+ // Additionally, our Self Init checker already warns about it. To avoid<br class="">+ // overwhelming the user with messages from both checkers, we model the case<br class="">+ // of '[super init]' in cases when it is not consumed by another expression<br class="">+ // as if the call preserves the value of 'self'; essentially, assuming it can<br class="">+ // never fail and return 'nil'.<br class="">+ // Note, we don't want to just stop tracking the value since we want the<br class="">+ // RetainCount checker to report leaks and use-after-free if SelfInit checker<br class="">+ // is turned off.<br class="">+ if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {<br class="">+ if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {<br class="">+<br class="">+ // Check if the message is not consumed, we know it will not be used in<br class="">+ // an assignment, ex: "self = [super init]".<br class="">+ const Expr *ME = MC->getOriginExpr();<br class="">+ const LocationContext *LCtx = MC->getLocationContext();<br class="">+ ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();<br class="">+ if (!PM.isConsumedExpr(ME)) {<br class="">+ RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);<br class="">+ ModifiableSummaryTemplate->setReceiverEffect(DoNothing);<br class="">+ ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());<br class="">+ }<br class="">+ }<br class="">+ }<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getSummary(const CallEvent &Call,<br class="">+ QualType ReceiverType) {<br class="">+ const RetainSummary *Summ;<br class="">+ switch (Call.getKind()) {<br class="">+ case CE_Function:<br class="">+ Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());<br class="">+ break;<br class="">+ case CE_CXXMember:<br class="">+ case CE_CXXMemberOperator:<br class="">+ case CE_Block:<br class="">+ case CE_CXXConstructor:<br class="">+ case CE_CXXDestructor:<br class="">+ case CE_CXXAllocator:<br class="">+ // FIXME: These calls are currently unsupported.<br class="">+ return getPersistentStopSummary();<br class="">+ case CE_ObjCMessage: {<br class="">+ const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);<br class="">+ if (Msg.isInstanceMessage())<br class="">+ Summ = getInstanceMethodSummary(Msg, ReceiverType);<br class="">+ else<br class="">+ Summ = getClassMethodSummary(Msg);<br class="">+ break;<br class="">+ }<br class="">+ }<br class="">+<br class="">+ updateSummaryForCall(Summ, Call);<br class="">+<br class="">+ assert(Summ && "Unknown call type?");<br class="">+ return Summ;<br class="">+}<br class="">+<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {<br class="">+ if (coreFoundation::followsCreateRule(FD))<br class="">+ return getCFSummaryCreateRule(FD);<br class="">+<br class="">+ return getCFSummaryGetRule(FD);<br class="">+}<br class="">+<br class="">+bool RetainSummaryManager::isTrustedReferenceCountImplementation(<br class="">+ const FunctionDecl *FD) {<br class="">+ return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");<br class="">+}<br class="">+<br class="">+bool RetainSummaryManager::canEval(const CallExpr *CE,<br class="">+ const FunctionDecl *FD,<br class="">+ bool &hasTrustedImplementationAnnotation) {<br class="">+ // For now, we're only handling the functions that return aliases of their<br class="">+ // arguments: CFRetain (and its families).<br class="">+ // Eventually we should add other functions we can model entirely,<br class="">+ // such as CFRelease, which don't invalidate their arguments or globals.<br class="">+ if (CE->getNumArgs() != 1)<br class="">+ return false;<br class="">+<br class="">+ IdentifierInfo *II = FD->getIdentifier();<br class="">+ if (!II)<br class="">+ return false;<br class="">+<br class="">+ StringRef FName = II->getName();<br class="">+ FName = FName.substr(FName.find_first_not_of('_'));<br class="">+<br class="">+ QualType ResultTy = CE->getCallReturnType(Ctx);<br class="">+ if (ResultTy->isObjCIdType()) {<br class="">+ return II->isStr("NSMakeCollectable");<br class="">+ } else if (ResultTy->isPointerType()) {<br class="">+ // Handle: (CF|CG|CV)Retain<br class="">+ // CFAutorelease<br class="">+ // It's okay to be a little sloppy here.<br class="">+ if (cocoa::isRefType(ResultTy, "CF", FName) ||<br class="">+ cocoa::isRefType(ResultTy, "CG", FName) ||<br class="">+ cocoa::isRefType(ResultTy, "CV", FName))<br class="">+ return isRetain(FD, FName) || isAutorelease(FD, FName) ||<br class="">+ isMakeCollectable(FName);<br class="">+<br class="">+ const FunctionDecl* FDD = FD->getDefinition();<br class="">+ if (FDD && isTrustedReferenceCountImplementation(FDD)) {<br class="">+ hasTrustedImplementationAnnotation = true;<br class="">+ return true;<br class="">+ }<br class="">+ }<br class="">+<br class="">+ return false;<br class="">+<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getUnarySummary(const FunctionType* FT,<br class="">+ UnaryFuncKind func) {<br class="">+<br class="">+ // Sanity check that this is *really* a unary function. This can<br class="">+ // happen if people do weird things.<br class="">+ const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);<br class="">+ if (!FTP || FTP->getNumParams() != 1)<br class="">+ return getPersistentStopSummary();<br class="">+<br class="">+ assert (ScratchArgs.isEmpty());<br class="">+<br class="">+ ArgEffect Effect;<br class="">+ switch (func) {<br class="">+ case cfretain: Effect = IncRef; break;<br class="">+ case cfrelease: Effect = DecRef; break;<br class="">+ case cfautorelease: Effect = Autorelease; break;<br class="">+ case cfmakecollectable: Effect = MakeCollectable; break;<br class="">+ }<br class="">+<br class="">+ ScratchArgs = AF.add(ScratchArgs, 0, Effect);<br class="">+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {<br class="">+ assert (ScratchArgs.isEmpty());<br class="">+<br class="">+ return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {<br class="">+ assert (ScratchArgs.isEmpty());<br class="">+ return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),<br class="">+ DoNothing, DoNothing);<br class="">+}<br class="">+<br class="">+<br class="">+<br class="">+<br class="">+//===----------------------------------------------------------------------===//<br class="">+// Summary creation for Selectors.<br class="">+//===----------------------------------------------------------------------===//<br class="">+<br class="">+Optional<RetEffect><br class="">+RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,<br class="">+ const Decl *D) {<br class="">+ if (cocoa::isCocoaObjectRef(RetTy)) {<br class="">+ if (D->hasAttr<NSReturnsRetainedAttr>())<br class="">+ return ObjCAllocRetE;<br class="">+<br class="">+ if (D->hasAttr<NSReturnsNotRetainedAttr>() ||<br class="">+ D->hasAttr<NSReturnsAutoreleasedAttr>())<br class="">+ return RetEffect::MakeNotOwned(RetEffect::ObjC);<br class="">+<br class="">+ } else if (!RetTy->isPointerType()) {<br class="">+ return None;<br class="">+ }<br class="">+<br class="">+ if (D->hasAttr<CFReturnsRetainedAttr>())<br class="">+ return RetEffect::MakeOwned(RetEffect::CF);<br class="">+ else if (hasRCAnnotation(D, "rc_ownership_returns_retained"))<br class="">+ return RetEffect::MakeOwned(RetEffect::Generalized);<br class="">+<br class="">+ if (D->hasAttr<CFReturnsNotRetainedAttr>())<br class="">+ return RetEffect::MakeNotOwned(RetEffect::CF);<br class="">+<br class="">+ return None;<br class="">+}<br class="">+<br class="">+void<br class="">+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,<br class="">+ const FunctionDecl *FD) {<br class="">+ if (!FD)<br class="">+ return;<br class="">+<br class="">+ assert(Summ && "Must have a summary to add annotations to.");<br class="">+ RetainSummaryTemplate Template(Summ, *this);<br class="">+<br class="">+ // Effects on the parameters.<br class="">+ unsigned parm_idx = 0;<br class="">+ for (FunctionDecl::param_const_iterator pi = FD->param_begin(),<br class="">+ pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {<br class="">+ const ParmVarDecl *pd = *pi;<br class="">+ if (pd->hasAttr<NSConsumedAttr>())<br class="">+ Template->addArg(AF, parm_idx, DecRefMsg);<br class="">+ else if (pd->hasAttr<CFConsumedAttr>() ||<br class="">+ hasRCAnnotation(pd, "rc_ownership_consumed"))<br class="">+ Template->addArg(AF, parm_idx, DecRef);<br class="">+ else if (pd->hasAttr<CFReturnsRetainedAttr>() ||<br class="">+ hasRCAnnotation(pd, "rc_ownership_returns_retained")) {<br class="">+ QualType PointeeTy = pd->getType()->getPointeeType();<br class="">+ if (!PointeeTy.isNull())<br class="">+ if (coreFoundation::isCFObjectRef(PointeeTy))<br class="">+ Template->addArg(AF, parm_idx, RetainedOutParameter);<br class="">+ } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {<br class="">+ QualType PointeeTy = pd->getType()->getPointeeType();<br class="">+ if (!PointeeTy.isNull())<br class="">+ if (coreFoundation::isCFObjectRef(PointeeTy))<br class="">+ Template->addArg(AF, parm_idx, UnretainedOutParameter);<br class="">+ }<br class="">+ }<br class="">+<br class="">+ QualType RetTy = FD->getReturnType();<br class="">+ if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))<br class="">+ Template->setRetEffect(*RetE);<br class="">+}<br class="">+<br class="">+void<br class="">+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,<br class="">+ const ObjCMethodDecl *MD) {<br class="">+ if (!MD)<br class="">+ return;<br class="">+<br class="">+ assert(Summ && "Must have a valid summary to add annotations to");<br class="">+ RetainSummaryTemplate Template(Summ, *this);<br class="">+<br class="">+ // Effects on the receiver.<br class="">+ if (MD->hasAttr<NSConsumesSelfAttr>())<br class="">+ Template->setReceiverEffect(DecRefMsg);<br class="">+<br class="">+ // Effects on the parameters.<br class="">+ unsigned parm_idx = 0;<br class="">+ for (ObjCMethodDecl::param_const_iterator<br class="">+ pi=MD->param_begin(), pe=MD->param_end();<br class="">+ pi != pe; ++pi, ++parm_idx) {<br class="">+ const ParmVarDecl *pd = *pi;<br class="">+ if (pd->hasAttr<NSConsumedAttr>())<br class="">+ Template->addArg(AF, parm_idx, DecRefMsg);<br class="">+ else if (pd->hasAttr<CFConsumedAttr>()) {<br class="">+ Template->addArg(AF, parm_idx, DecRef);<br class="">+ } else if (pd->hasAttr<CFReturnsRetainedAttr>()) {<br class="">+ QualType PointeeTy = pd->getType()->getPointeeType();<br class="">+ if (!PointeeTy.isNull())<br class="">+ if (coreFoundation::isCFObjectRef(PointeeTy))<br class="">+ Template->addArg(AF, parm_idx, RetainedOutParameter);<br class="">+ } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {<br class="">+ QualType PointeeTy = pd->getType()->getPointeeType();<br class="">+ if (!PointeeTy.isNull())<br class="">+ if (coreFoundation::isCFObjectRef(PointeeTy))<br class="">+ Template->addArg(AF, parm_idx, UnretainedOutParameter);<br class="">+ }<br class="">+ }<br class="">+<br class="">+ QualType RetTy = MD->getReturnType();<br class="">+ if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))<br class="">+ Template->setRetEffect(*RetE);<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,<br class="">+ Selector S, QualType RetTy) {<br class="">+ // Any special effects?<br class="">+ ArgEffect ReceiverEff = DoNothing;<br class="">+ RetEffect ResultEff = RetEffect::MakeNoRet();<br class="">+<br class="">+ // Check the method family, and apply any default annotations.<br class="">+ switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {<br class="">+ case OMF_None:<br class="">+ case OMF_initialize:<br class="">+ case OMF_performSelector:<br class="">+ // Assume all Objective-C methods follow Cocoa Memory Management rules.<br class="">+ // FIXME: Does the non-threaded performSelector family really belong here?<br class="">+ // The selector could be, say, @selector(copy).<br class="">+ if (cocoa::isCocoaObjectRef(RetTy))<br class="">+ ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);<br class="">+ else if (coreFoundation::isCFObjectRef(RetTy)) {<br class="">+ // ObjCMethodDecl currently doesn't consider CF objects as valid return<br class="">+ // values for alloc, new, copy, or mutableCopy, so we have to<br class="">+ // double-check with the selector. This is ugly, but there aren't that<br class="">+ // many Objective-C methods that return CF objects, right?<br class="">+ if (MD) {<br class="">+ switch (S.getMethodFamily()) {<br class="">+ case OMF_alloc:<br class="">+ case OMF_new:<br class="">+ case OMF_copy:<br class="">+ case OMF_mutableCopy:<br class="">+ ResultEff = RetEffect::MakeOwned(RetEffect::CF);<br class="">+ break;<br class="">+ default:<br class="">+ ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);<br class="">+ break;<br class="">+ }<br class="">+ } else {<br class="">+ ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);<br class="">+ }<br class="">+ }<br class="">+ break;<br class="">+ case OMF_init:<br class="">+ ResultEff = ObjCInitRetE;<br class="">+ ReceiverEff = DecRefMsg;<br class="">+ break;<br class="">+ case OMF_alloc:<br class="">+ case OMF_new:<br class="">+ case OMF_copy:<br class="">+ case OMF_mutableCopy:<br class="">+ if (cocoa::isCocoaObjectRef(RetTy))<br class="">+ ResultEff = ObjCAllocRetE;<br class="">+ else if (coreFoundation::isCFObjectRef(RetTy))<br class="">+ ResultEff = RetEffect::MakeOwned(RetEffect::CF);<br class="">+ break;<br class="">+ case OMF_autorelease:<br class="">+ ReceiverEff = Autorelease;<br class="">+ break;<br class="">+ case OMF_retain:<br class="">+ ReceiverEff = IncRefMsg;<br class="">+ break;<br class="">+ case OMF_release:<br class="">+ ReceiverEff = DecRefMsg;<br class="">+ break;<br class="">+ case OMF_dealloc:<br class="">+ ReceiverEff = Dealloc;<br class="">+ break;<br class="">+ case OMF_self:<br class="">+ // -self is handled specially by the ExprEngine to propagate the receiver.<br class="">+ break;<br class="">+ case OMF_retainCount:<br class="">+ case OMF_finalize:<br class="">+ // These methods don't return objects.<br class="">+ break;<br class="">+ }<br class="">+<br class="">+ // If one of the arguments in the selector has the keyword 'delegate' we<br class="">+ // should stop tracking the reference count for the receiver. This is<br class="">+ // because the reference count is quite possibly handled by a delegate<br class="">+ // method.<br class="">+ if (S.isKeywordSelector()) {<br class="">+ for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {<br class="">+ StringRef Slot = S.getNameForSlot(i);<br class="">+ if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {<br class="">+ if (ResultEff == ObjCInitRetE)<br class="">+ ResultEff = RetEffect::MakeNoRetHard();<br class="">+ else<br class="">+ ReceiverEff = StopTrackingHard;<br class="">+ }<br class="">+ }<br class="">+ }<br class="">+<br class="">+ if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&<br class="">+ ResultEff.getKind() == RetEffect::NoRet)<br class="">+ return getDefaultSummary();<br class="">+<br class="">+ return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);<br class="">+}<br class="">+<br class="">+const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(<br class="">+ const ObjCMethodCall &Msg, QualType ReceiverType) {<br class="">+ const ObjCInterfaceDecl *ReceiverClass = nullptr;<br class="">+<br class="">+ // We do better tracking of the type of the object than the core ExprEngine.<br class="">+ // See if we have its type in our private state.<br class="">+ if (!ReceiverType.isNull())<br class="">+ if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())<br class="">+ ReceiverClass = PT->getInterfaceDecl();<br class="">+<br class="">+ // If we don't know what kind of object this is, fall back to its static type.<br class="">+ if (!ReceiverClass)<br class="">+ ReceiverClass = Msg.getReceiverInterface();<br class="">+<br class="">+ // FIXME: The receiver could be a reference to a class, meaning that<br class="">+ // we should use the class method.<br class="">+ // id x = [NSObject class];<br class="">+ // [x performSelector:... withObject:... afterDelay:...];<br class="">+ Selector S = Msg.getSelector();<br class="">+ const ObjCMethodDecl *Method = Msg.getDecl();<br class="">+ if (!Method && ReceiverClass)<br class="">+ Method = ReceiverClass->getInstanceMethod(S);<br class="">+<br class="">+ return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),<br class="">+ ObjCMethodSummaries);<br class="">+}<br class="">+<br class="">+const RetainSummary *<br class="">+RetainSummaryManager::getMethodSummary(Se<br class=""></blockquote><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">--<span class="Apple-converted-space"> </span></span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><span style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none; float: none; display: inline !important;" class="">Bruno Cardoso Lopes</span><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""><a href="http://www.brunocardoso.cc/" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255);" class="">http://www.brunocardoso.cc</a><br style="caret-color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration: none;" class=""></div></blockquote></div><br class=""></body></html>