xref: /llvm-project/clang/lib/Analysis/RetainSummaryManager.cpp (revision 0ac54fad538eabd9b368f6e2460898621828a72b)
1 //== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines summaries implementation for retain counting, which
11 //  implements a reference count checker for Core Foundation and Cocoa
12 //  on (Mac OS X).
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "clang/Analysis/RetainSummaryManager.h"
17 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
18 #include "clang/AST/Attr.h"
19 #include "clang/AST/DeclCXX.h"
20 #include "clang/AST/DeclObjC.h"
21 #include "clang/AST/ParentMap.h"
22 
23 using namespace clang;
24 using namespace ento;
25 
26 ArgEffects RetainSummaryManager::getArgEffects() {
27   ArgEffects AE = ScratchArgs;
28   ScratchArgs = AF.getEmptyMap();
29   return AE;
30 }
31 
32 const RetainSummary *
33 RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
34   // Unique "simple" summaries -- those without ArgEffects.
35   if (OldSumm.isSimple()) {
36     ::llvm::FoldingSetNodeID ID;
37     OldSumm.Profile(ID);
38 
39     void *Pos;
40     CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
41 
42     if (!N) {
43       N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
44       new (N) CachedSummaryNode(OldSumm);
45       SimpleSummaries.InsertNode(N, Pos);
46     }
47 
48     return &N->getValue();
49   }
50 
51   RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
52   new (Summ) RetainSummary(OldSumm);
53   return Summ;
54 }
55 
56 static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
57   for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
58     if (Ann->getAnnotation() == rcAnnotation)
59       return true;
60   }
61   return false;
62 }
63 
64 static bool isRetain(const FunctionDecl *FD, StringRef FName) {
65   return FName.startswith_lower("retain") || FName.endswith_lower("retain");
66 }
67 
68 static bool isRelease(const FunctionDecl *FD, StringRef FName) {
69   return FName.startswith_lower("release") || FName.endswith_lower("release");
70 }
71 
72 static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
73   return FName.startswith_lower("autorelease") ||
74          FName.endswith_lower("autorelease");
75 }
76 
77 static bool isMakeCollectable(StringRef FName) {
78   return FName.contains_lower("MakeCollectable");
79 }
80 
81 const RetainSummary *
82 RetainSummaryManager::generateSummary(const FunctionDecl *FD,
83                                       bool &AllowAnnotations) {
84   // We generate "stop" summaries for implicitly defined functions.
85   if (FD->isImplicit()) {
86     return getPersistentStopSummary();
87   }
88 
89   // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the
90   // function's type.
91   const FunctionType *FT = FD->getType()->getAs<FunctionType>();
92   const IdentifierInfo *II = FD->getIdentifier();
93   if (!II)
94     return getDefaultSummary();
95 
96   StringRef FName = II->getName();
97 
98   // Strip away preceding '_'.  Doing this here will effect all the checks
99   // down below.
100   FName = FName.substr(FName.find_first_not_of('_'));
101 
102   // Inspect the result type.
103   QualType RetTy = FT->getReturnType();
104   std::string RetTyName = RetTy.getAsString();
105 
106   // FIXME: This should all be refactored into a chain of "summary lookup"
107   //  filters.
108   assert(ScratchArgs.isEmpty());
109 
110   if (FName == "pthread_create" || FName == "pthread_setspecific") {
111     // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
112     // This will be addressed better with IPA.
113     return getPersistentStopSummary();
114   } else if(FName == "NSMakeCollectable") {
115     // Handle: id NSMakeCollectable(CFTypeRef)
116     AllowAnnotations = false;
117     return RetTy->isObjCIdType() ? getUnarySummary(FT, cfmakecollectable)
118                                  : getPersistentStopSummary();
119   } else if (FName == "CFPlugInInstanceCreate") {
120     return getPersistentSummary(RetEffect::MakeNoRet());
121   } else if (FName == "IORegistryEntrySearchCFProperty" ||
122              (RetTyName == "CFMutableDictionaryRef" &&
123               (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||
124                FName == "IOServiceNameMatching" ||
125                FName == "IORegistryEntryIDMatching" ||
126                FName == "IOOpenFirmwarePathMatching"))) {
127     // Part of <rdar://problem/6961230>. (IOKit)
128     // This should be addressed using a API table.
129     return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing,
130                              DoNothing);
131   } else if (FName == "IOServiceGetMatchingService" ||
132              FName == "IOServiceGetMatchingServices") {
133     // FIXES: <rdar://problem/6326900>
134     // This should be addressed using a API table.  This strcmp is also
135     // a little gross, but there is no need to super optimize here.
136     ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
137     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
138   } else if (FName == "IOServiceAddNotification" ||
139              FName == "IOServiceAddMatchingNotification") {
140     // Part of <rdar://problem/6961230>. (IOKit)
141     // This should be addressed using a API table.
142     ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
143     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
144   } else if (FName == "CVPixelBufferCreateWithBytes") {
145     // FIXES: <rdar://problem/7283567>
146     // Eventually this can be improved by recognizing that the pixel
147     // buffer passed to CVPixelBufferCreateWithBytes is released via
148     // a callback and doing full IPA to make sure this is done correctly.
149     // FIXME: This function has an out parameter that returns an
150     // allocated object.
151     ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
152     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
153   } else if (FName == "CGBitmapContextCreateWithData") {
154     // FIXES: <rdar://problem/7358899>
155     // Eventually this can be improved by recognizing that 'releaseInfo'
156     // passed to CGBitmapContextCreateWithData is released via
157     // a callback and doing full IPA to make sure this is done correctly.
158     ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
159     return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF), DoNothing,
160                              DoNothing);
161   } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
162     // FIXES: <rdar://problem/7283567>
163     // Eventually this can be improved by recognizing that the pixel
164     // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
165     // via a callback and doing full IPA to make sure this is done
166     // correctly.
167     ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
168     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
169   } else if (FName == "VTCompressionSessionEncodeFrame") {
170     // The context argument passed to VTCompressionSessionEncodeFrame()
171     // is passed to the callback specified when creating the session
172     // (e.g. with VTCompressionSessionCreate()) which can release it.
173     // To account for this possibility, conservatively stop tracking
174     // the context.
175     ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);
176     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
177   } else if (FName == "dispatch_set_context" ||
178              FName == "xpc_connection_set_context") {
179     // <rdar://problem/11059275> - The analyzer currently doesn't have
180     // a good way to reason about the finalizer function for libdispatch.
181     // If we pass a context object that is memory managed, stop tracking it.
182     // <rdar://problem/13783514> - Same problem, but for XPC.
183     // FIXME: this hack should possibly go away once we can handle
184     // libdispatch and XPC finalizers.
185     ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
186     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
187   } else if (FName.startswith("NSLog")) {
188     return getDoNothingSummary();
189   } else if (FName.startswith("NS") &&
190              (FName.find("Insert") != StringRef::npos)) {
191     // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
192     // be deallocated by NSMapRemove. (radar://11152419)
193     ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
194     ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
195     return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
196   }
197 
198   if (RetTy->isPointerType()) {
199     // For CoreFoundation ('CF') types.
200     if (cocoa::isRefType(RetTy, "CF", FName)) {
201       if (isRetain(FD, FName)) {
202         // CFRetain isn't supposed to be annotated. However, this may as well
203         // be a user-made "safe" CFRetain function that is incorrectly
204         // annotated as cf_returns_retained due to lack of better options.
205         // We want to ignore such annotation.
206         AllowAnnotations = false;
207 
208         return getUnarySummary(FT, cfretain);
209       } else if (isAutorelease(FD, FName)) {
210         // The headers use cf_consumed, but we can fully model CFAutorelease
211         // ourselves.
212         AllowAnnotations = false;
213 
214         return getUnarySummary(FT, cfautorelease);
215       } else if (isMakeCollectable(FName)) {
216         AllowAnnotations = false;
217         return getUnarySummary(FT, cfmakecollectable);
218       } else {
219         return getCFCreateGetRuleSummary(FD);
220       }
221     }
222 
223     // For CoreGraphics ('CG') and CoreVideo ('CV') types.
224     if (cocoa::isRefType(RetTy, "CG", FName) ||
225         cocoa::isRefType(RetTy, "CV", FName)) {
226       if (isRetain(FD, FName))
227         return getUnarySummary(FT, cfretain);
228       else
229         return getCFCreateGetRuleSummary(FD);
230     }
231 
232     // For all other CF-style types, use the Create/Get
233     // rule for summaries but don't support Retain functions
234     // with framework-specific prefixes.
235     if (coreFoundation::isCFObjectRef(RetTy)) {
236       return getCFCreateGetRuleSummary(FD);
237     }
238 
239     if (FD->hasAttr<CFAuditedTransferAttr>()) {
240       return getCFCreateGetRuleSummary(FD);
241     }
242   }
243 
244   // Check for release functions, the only kind of functions that we care
245   // about that don't return a pointer type.
246   if (FName.size() >= 2 && FName[0] == 'C' &&
247       (FName[1] == 'F' || FName[1] == 'G')) {
248     // Test for 'CGCF'.
249     FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
250 
251     if (isRelease(FD, FName))
252       return getUnarySummary(FT, cfrelease);
253     else {
254       assert(ScratchArgs.isEmpty());
255       // Remaining CoreFoundation and CoreGraphics functions.
256       // We use to assume that they all strictly followed the ownership idiom
257       // and that ownership cannot be transferred.  While this is technically
258       // correct, many methods allow a tracked object to escape.  For example:
259       //
260       //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
261       //   CFDictionaryAddValue(y, key, x);
262       //   CFRelease(x);
263       //   ... it is okay to use 'x' since 'y' has a reference to it
264       //
265       // We handle this and similar cases with the follow heuristic.  If the
266       // function name contains "InsertValue", "SetValue", "AddValue",
267       // "AppendValue", or "SetAttribute", then we assume that arguments may
268       // "escape."  This means that something else holds on to the object,
269       // allowing it be used even after its local retain count drops to 0.
270       ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
271                      StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
272                      StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
273                      StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
274                      StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
275                         ? MayEscape
276                         : DoNothing;
277 
278       return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
279     }
280   }
281 
282   return getDefaultSummary();
283 }
284 
285 const RetainSummary *
286 RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
287   // If we don't know what function we're calling, use our default summary.
288   if (!FD)
289     return getDefaultSummary();
290 
291   // Look up a summary in our cache of FunctionDecls -> Summaries.
292   FuncSummariesTy::iterator I = FuncSummaries.find(FD);
293   if (I != FuncSummaries.end())
294     return I->second;
295 
296   // No summary?  Generate one.
297   bool AllowAnnotations = true;
298   const RetainSummary *S = generateSummary(FD, AllowAnnotations);
299 
300   // Annotations override defaults.
301   if (AllowAnnotations)
302     updateSummaryFromAnnotations(S, FD);
303 
304   FuncSummaries[FD] = S;
305   return S;
306 }
307 
308 //===----------------------------------------------------------------------===//
309 // Summary creation for functions (largely uses of Core Foundation).
310 //===----------------------------------------------------------------------===//
311 
312 static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
313   switch (E) {
314   case DoNothing:
315   case Autorelease:
316   case DecRefBridgedTransferred:
317   case IncRef:
318   case IncRefMsg:
319   case MakeCollectable:
320   case UnretainedOutParameter:
321   case RetainedOutParameter:
322   case MayEscape:
323   case StopTracking:
324   case StopTrackingHard:
325     return StopTrackingHard;
326   case DecRef:
327   case DecRefAndStopTrackingHard:
328     return DecRefAndStopTrackingHard;
329   case DecRefMsg:
330   case DecRefMsgAndStopTrackingHard:
331     return DecRefMsgAndStopTrackingHard;
332   case Dealloc:
333     return Dealloc;
334   }
335 
336   llvm_unreachable("Unknown ArgEffect kind");
337 }
338 
339 void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
340                                                 const CallEvent &Call) {
341   if (Call.hasNonZeroCallbackArg()) {
342     ArgEffect RecEffect =
343       getStopTrackingHardEquivalent(S->getReceiverEffect());
344     ArgEffect DefEffect =
345       getStopTrackingHardEquivalent(S->getDefaultArgEffect());
346 
347     ArgEffects CustomArgEffects = S->getArgEffects();
348     for (ArgEffects::iterator I = CustomArgEffects.begin(),
349                               E = CustomArgEffects.end();
350          I != E; ++I) {
351       ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
352       if (Translated != DefEffect)
353         ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
354     }
355 
356     RetEffect RE = RetEffect::MakeNoRetHard();
357 
358     // Special cases where the callback argument CANNOT free the return value.
359     // This can generally only happen if we know that the callback will only be
360     // called when the return value is already being deallocated.
361     if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
362       if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
363         // When the CGBitmapContext is deallocated, the callback here will free
364         // the associated data buffer.
365         // The callback in dispatch_data_create frees the buffer, but not
366         // the data object.
367         if (Name->isStr("CGBitmapContextCreateWithData") ||
368             Name->isStr("dispatch_data_create"))
369           RE = S->getRetEffect();
370       }
371     }
372 
373     S = getPersistentSummary(RE, RecEffect, DefEffect);
374   }
375 
376   // Special case '[super init];' and '[self init];'
377   //
378   // Even though calling '[super init]' without assigning the result to self
379   // and checking if the parent returns 'nil' is a bad pattern, it is common.
380   // Additionally, our Self Init checker already warns about it. To avoid
381   // overwhelming the user with messages from both checkers, we model the case
382   // of '[super init]' in cases when it is not consumed by another expression
383   // as if the call preserves the value of 'self'; essentially, assuming it can
384   // never fail and return 'nil'.
385   // Note, we don't want to just stop tracking the value since we want the
386   // RetainCount checker to report leaks and use-after-free if SelfInit checker
387   // is turned off.
388   if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
389     if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
390 
391       // Check if the message is not consumed, we know it will not be used in
392       // an assignment, ex: "self = [super init]".
393       const Expr *ME = MC->getOriginExpr();
394       const LocationContext *LCtx = MC->getLocationContext();
395       ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
396       if (!PM.isConsumedExpr(ME)) {
397         RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
398         ModifiableSummaryTemplate->setReceiverEffect(DoNothing);
399         ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
400       }
401     }
402   }
403 }
404 
405 const RetainSummary *
406 RetainSummaryManager::getSummary(const CallEvent &Call,
407                                  QualType ReceiverType) {
408   const RetainSummary *Summ;
409   switch (Call.getKind()) {
410   case CE_Function:
411     Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
412     break;
413   case CE_CXXMember:
414   case CE_CXXMemberOperator:
415   case CE_Block:
416   case CE_CXXConstructor:
417   case CE_CXXDestructor:
418   case CE_CXXAllocator:
419     // FIXME: These calls are currently unsupported.
420     return getPersistentStopSummary();
421   case CE_ObjCMessage: {
422     const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
423     if (Msg.isInstanceMessage())
424       Summ = getInstanceMethodSummary(Msg, ReceiverType);
425     else
426       Summ = getClassMethodSummary(Msg);
427     break;
428   }
429   }
430 
431   updateSummaryForCall(Summ, Call);
432 
433   assert(Summ && "Unknown call type?");
434   return Summ;
435 }
436 
437 
438 const RetainSummary *
439 RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
440   if (coreFoundation::followsCreateRule(FD))
441     return getCFSummaryCreateRule(FD);
442 
443   return getCFSummaryGetRule(FD);
444 }
445 
446 bool RetainSummaryManager::isTrustedReferenceCountImplementation(
447     const FunctionDecl *FD) {
448   return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
449 }
450 
451 bool RetainSummaryManager::canEval(const CallExpr *CE,
452                                    const FunctionDecl *FD,
453                                    bool &hasTrustedImplementationAnnotation) {
454   // For now, we're only handling the functions that return aliases of their
455   // arguments: CFRetain (and its families).
456   // Eventually we should add other functions we can model entirely,
457   // such as CFRelease, which don't invalidate their arguments or globals.
458   if (CE->getNumArgs() != 1)
459     return false;
460 
461   IdentifierInfo *II = FD->getIdentifier();
462   if (!II)
463     return false;
464 
465   StringRef FName = II->getName();
466   FName = FName.substr(FName.find_first_not_of('_'));
467 
468   QualType ResultTy = CE->getCallReturnType(Ctx);
469   if (ResultTy->isObjCIdType()) {
470     return II->isStr("NSMakeCollectable");
471   } else if (ResultTy->isPointerType()) {
472     // Handle: (CF|CG|CV)Retain
473     //         CFAutorelease
474     // It's okay to be a little sloppy here.
475     if (cocoa::isRefType(ResultTy, "CF", FName) ||
476         cocoa::isRefType(ResultTy, "CG", FName) ||
477         cocoa::isRefType(ResultTy, "CV", FName))
478       return isRetain(FD, FName) || isAutorelease(FD, FName) ||
479              isMakeCollectable(FName);
480 
481     const FunctionDecl* FDD = FD->getDefinition();
482     if (FDD && isTrustedReferenceCountImplementation(FDD)) {
483       hasTrustedImplementationAnnotation = true;
484       return true;
485     }
486   }
487 
488   return false;
489 
490 }
491 
492 const RetainSummary *
493 RetainSummaryManager::getUnarySummary(const FunctionType* FT,
494                                       UnaryFuncKind func) {
495 
496   // Sanity check that this is *really* a unary function.  This can
497   // happen if people do weird things.
498   const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
499   if (!FTP || FTP->getNumParams() != 1)
500     return getPersistentStopSummary();
501 
502   assert (ScratchArgs.isEmpty());
503 
504   ArgEffect Effect;
505   switch (func) {
506   case cfretain: Effect = IncRef; break;
507   case cfrelease: Effect = DecRef; break;
508   case cfautorelease: Effect = Autorelease; break;
509   case cfmakecollectable: Effect = MakeCollectable; break;
510   }
511 
512   ScratchArgs = AF.add(ScratchArgs, 0, Effect);
513   return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
514 }
515 
516 const RetainSummary *
517 RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
518   assert (ScratchArgs.isEmpty());
519 
520   return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
521 }
522 
523 const RetainSummary *
524 RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
525   assert (ScratchArgs.isEmpty());
526   return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
527                               DoNothing, DoNothing);
528 }
529 
530 
531 
532 
533 //===----------------------------------------------------------------------===//
534 // Summary creation for Selectors.
535 //===----------------------------------------------------------------------===//
536 
537 Optional<RetEffect>
538 RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
539                                                   const Decl *D) {
540   if (cocoa::isCocoaObjectRef(RetTy)) {
541     if (D->hasAttr<NSReturnsRetainedAttr>())
542       return ObjCAllocRetE;
543 
544     if (D->hasAttr<NSReturnsNotRetainedAttr>() ||
545         D->hasAttr<NSReturnsAutoreleasedAttr>())
546       return RetEffect::MakeNotOwned(RetEffect::ObjC);
547 
548   } else if (!RetTy->isPointerType()) {
549     return None;
550   }
551 
552   if (D->hasAttr<CFReturnsRetainedAttr>())
553     return RetEffect::MakeOwned(RetEffect::CF);
554   else if (hasRCAnnotation(D, "rc_ownership_returns_retained"))
555     return RetEffect::MakeOwned(RetEffect::Generalized);
556 
557   if (D->hasAttr<CFReturnsNotRetainedAttr>())
558     return RetEffect::MakeNotOwned(RetEffect::CF);
559 
560   return None;
561 }
562 
563 void
564 RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
565                                                    const FunctionDecl *FD) {
566   if (!FD)
567     return;
568 
569   assert(Summ && "Must have a summary to add annotations to.");
570   RetainSummaryTemplate Template(Summ, *this);
571 
572   // Effects on the parameters.
573   unsigned parm_idx = 0;
574   for (FunctionDecl::param_const_iterator pi = FD->param_begin(),
575          pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) {
576     const ParmVarDecl *pd = *pi;
577     if (pd->hasAttr<NSConsumedAttr>())
578       Template->addArg(AF, parm_idx, DecRefMsg);
579     else if (pd->hasAttr<CFConsumedAttr>() ||
580              hasRCAnnotation(pd, "rc_ownership_consumed"))
581       Template->addArg(AF, parm_idx, DecRef);
582     else if (pd->hasAttr<CFReturnsRetainedAttr>() ||
583              hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
584       QualType PointeeTy = pd->getType()->getPointeeType();
585       if (!PointeeTy.isNull())
586         if (coreFoundation::isCFObjectRef(PointeeTy))
587           Template->addArg(AF, parm_idx, RetainedOutParameter);
588     } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
589       QualType PointeeTy = pd->getType()->getPointeeType();
590       if (!PointeeTy.isNull())
591         if (coreFoundation::isCFObjectRef(PointeeTy))
592           Template->addArg(AF, parm_idx, UnretainedOutParameter);
593     }
594   }
595 
596   QualType RetTy = FD->getReturnType();
597   if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
598     Template->setRetEffect(*RetE);
599 }
600 
601 void
602 RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
603                                                    const ObjCMethodDecl *MD) {
604   if (!MD)
605     return;
606 
607   assert(Summ && "Must have a valid summary to add annotations to");
608   RetainSummaryTemplate Template(Summ, *this);
609 
610   // Effects on the receiver.
611   if (MD->hasAttr<NSConsumesSelfAttr>())
612     Template->setReceiverEffect(DecRefMsg);
613 
614   // Effects on the parameters.
615   unsigned parm_idx = 0;
616   for (ObjCMethodDecl::param_const_iterator
617          pi=MD->param_begin(), pe=MD->param_end();
618        pi != pe; ++pi, ++parm_idx) {
619     const ParmVarDecl *pd = *pi;
620     if (pd->hasAttr<NSConsumedAttr>())
621       Template->addArg(AF, parm_idx, DecRefMsg);
622     else if (pd->hasAttr<CFConsumedAttr>()) {
623       Template->addArg(AF, parm_idx, DecRef);
624     } else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
625       QualType PointeeTy = pd->getType()->getPointeeType();
626       if (!PointeeTy.isNull())
627         if (coreFoundation::isCFObjectRef(PointeeTy))
628           Template->addArg(AF, parm_idx, RetainedOutParameter);
629     } else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
630       QualType PointeeTy = pd->getType()->getPointeeType();
631       if (!PointeeTy.isNull())
632         if (coreFoundation::isCFObjectRef(PointeeTy))
633           Template->addArg(AF, parm_idx, UnretainedOutParameter);
634     }
635   }
636 
637   QualType RetTy = MD->getReturnType();
638   if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
639     Template->setRetEffect(*RetE);
640 }
641 
642 const RetainSummary *
643 RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
644                                                Selector S, QualType RetTy) {
645   // Any special effects?
646   ArgEffect ReceiverEff = DoNothing;
647   RetEffect ResultEff = RetEffect::MakeNoRet();
648 
649   // Check the method family, and apply any default annotations.
650   switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
651     case OMF_None:
652     case OMF_initialize:
653     case OMF_performSelector:
654       // Assume all Objective-C methods follow Cocoa Memory Management rules.
655       // FIXME: Does the non-threaded performSelector family really belong here?
656       // The selector could be, say, @selector(copy).
657       if (cocoa::isCocoaObjectRef(RetTy))
658         ResultEff = RetEffect::MakeNotOwned(RetEffect::ObjC);
659       else if (coreFoundation::isCFObjectRef(RetTy)) {
660         // ObjCMethodDecl currently doesn't consider CF objects as valid return
661         // values for alloc, new, copy, or mutableCopy, so we have to
662         // double-check with the selector. This is ugly, but there aren't that
663         // many Objective-C methods that return CF objects, right?
664         if (MD) {
665           switch (S.getMethodFamily()) {
666           case OMF_alloc:
667           case OMF_new:
668           case OMF_copy:
669           case OMF_mutableCopy:
670             ResultEff = RetEffect::MakeOwned(RetEffect::CF);
671             break;
672           default:
673             ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
674             break;
675           }
676         } else {
677           ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
678         }
679       }
680       break;
681     case OMF_init:
682       ResultEff = ObjCInitRetE;
683       ReceiverEff = DecRefMsg;
684       break;
685     case OMF_alloc:
686     case OMF_new:
687     case OMF_copy:
688     case OMF_mutableCopy:
689       if (cocoa::isCocoaObjectRef(RetTy))
690         ResultEff = ObjCAllocRetE;
691       else if (coreFoundation::isCFObjectRef(RetTy))
692         ResultEff = RetEffect::MakeOwned(RetEffect::CF);
693       break;
694     case OMF_autorelease:
695       ReceiverEff = Autorelease;
696       break;
697     case OMF_retain:
698       ReceiverEff = IncRefMsg;
699       break;
700     case OMF_release:
701       ReceiverEff = DecRefMsg;
702       break;
703     case OMF_dealloc:
704       ReceiverEff = Dealloc;
705       break;
706     case OMF_self:
707       // -self is handled specially by the ExprEngine to propagate the receiver.
708       break;
709     case OMF_retainCount:
710     case OMF_finalize:
711       // These methods don't return objects.
712       break;
713   }
714 
715   // If one of the arguments in the selector has the keyword 'delegate' we
716   // should stop tracking the reference count for the receiver.  This is
717   // because the reference count is quite possibly handled by a delegate
718   // method.
719   if (S.isKeywordSelector()) {
720     for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
721       StringRef Slot = S.getNameForSlot(i);
722       if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
723         if (ResultEff == ObjCInitRetE)
724           ResultEff = RetEffect::MakeNoRetHard();
725         else
726           ReceiverEff = StopTrackingHard;
727       }
728     }
729   }
730 
731   if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
732       ResultEff.getKind() == RetEffect::NoRet)
733     return getDefaultSummary();
734 
735   return getPersistentSummary(ResultEff, ReceiverEff, MayEscape);
736 }
737 
738 const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
739     const ObjCMethodCall &Msg, QualType ReceiverType) {
740   const ObjCInterfaceDecl *ReceiverClass = nullptr;
741 
742   // We do better tracking of the type of the object than the core ExprEngine.
743   // See if we have its type in our private state.
744   if (!ReceiverType.isNull())
745     if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
746       ReceiverClass = PT->getInterfaceDecl();
747 
748   // If we don't know what kind of object this is, fall back to its static type.
749   if (!ReceiverClass)
750     ReceiverClass = Msg.getReceiverInterface();
751 
752   // FIXME: The receiver could be a reference to a class, meaning that
753   //  we should use the class method.
754   // id x = [NSObject class];
755   // [x performSelector:... withObject:... afterDelay:...];
756   Selector S = Msg.getSelector();
757   const ObjCMethodDecl *Method = Msg.getDecl();
758   if (!Method && ReceiverClass)
759     Method = ReceiverClass->getInstanceMethod(S);
760 
761   return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
762                           ObjCMethodSummaries);
763 }
764 
765 const RetainSummary *
766 RetainSummaryManager::getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
767                                        const ObjCMethodDecl *MD, QualType RetTy,
768                                        ObjCMethodSummariesTy &CachedSummaries) {
769 
770   // Look up a summary in our summary cache.
771   const RetainSummary *Summ = CachedSummaries.find(ID, S);
772 
773   if (!Summ) {
774     Summ = getStandardMethodSummary(MD, S, RetTy);
775 
776     // Annotations override defaults.
777     updateSummaryFromAnnotations(Summ, MD);
778 
779     // Memoize the summary.
780     CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
781   }
782 
783   return Summ;
784 }
785 
786 void RetainSummaryManager::InitializeClassMethodSummaries() {
787   assert(ScratchArgs.isEmpty());
788   // Create the [NSAssertionHandler currentHander] summary.
789   addClassMethSummary("NSAssertionHandler", "currentHandler",
790                 getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));
791 
792   // Create the [NSAutoreleasePool addObject:] summary.
793   ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
794   addClassMethSummary("NSAutoreleasePool", "addObject",
795                       getPersistentSummary(RetEffect::MakeNoRet(),
796                                            DoNothing, Autorelease));
797 }
798 
799 void RetainSummaryManager::InitializeMethodSummaries() {
800 
801   assert (ScratchArgs.isEmpty());
802 
803   // Create the "init" selector.  It just acts as a pass-through for the
804   // receiver.
805   const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, DecRefMsg);
806   addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
807 
808   // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
809   // claims the receiver and returns a retained object.
810   addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
811                          InitSumm);
812 
813   // The next methods are allocators.
814   const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
815   const RetainSummary *CFAllocSumm =
816     getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
817 
818   // Create the "retain" selector.
819   RetEffect NoRet = RetEffect::MakeNoRet();
820   const RetainSummary *Summ = getPersistentSummary(NoRet, IncRefMsg);
821   addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
822 
823   // Create the "release" selector.
824   Summ = getPersistentSummary(NoRet, DecRefMsg);
825   addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
826 
827   // Create the -dealloc summary.
828   Summ = getPersistentSummary(NoRet, Dealloc);
829   addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
830 
831   // Create the "autorelease" selector.
832   Summ = getPersistentSummary(NoRet, Autorelease);
833   addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
834 
835   // For NSWindow, allocated objects are (initially) self-owned.
836   // FIXME: For now we opt for false negatives with NSWindow, as these objects
837   //  self-own themselves.  However, they only do this once they are displayed.
838   //  Thus, we need to track an NSWindow's display status.
839   //  This is tracked in <rdar://problem/6062711>.
840   //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
841   const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
842                                                    StopTracking,
843                                                    StopTracking);
844 
845   addClassMethSummary("NSWindow", "alloc", NoTrackYet);
846 
847   // For NSPanel (which subclasses NSWindow), allocated objects are not
848   //  self-owned.
849   // FIXME: For now we don't track NSPanels. object for the same reason
850   //   as for NSWindow objects.
851   addClassMethSummary("NSPanel", "alloc", NoTrackYet);
852 
853   // For NSNull, objects returned by +null are singletons that ignore
854   // retain/release semantics.  Just don't track them.
855   // <rdar://problem/12858915>
856   addClassMethSummary("NSNull", "null", NoTrackYet);
857 
858   // Don't track allocated autorelease pools, as it is okay to prematurely
859   // exit a method.
860   addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
861   addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
862   addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
863 
864   // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
865   addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
866   addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
867 
868   // Create summaries for CIContext, 'createCGImage' and
869   // 'createCGLayerWithSize'.  These objects are CF objects, and are not
870   // automatically garbage collected.
871   addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
872   addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
873                      "format", "colorSpace");
874   addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
875 }
876 
877 CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
878   ASTContext &Ctx = MD->getASTContext();
879   LangOptions L = Ctx.getLangOpts();
880   RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);
881   const RetainSummary *S = M.getMethodSummary(MD);
882   CallEffects CE(S->getRetEffect());
883   CE.Receiver = S->getReceiverEffect();
884   unsigned N = MD->param_size();
885   for (unsigned i = 0; i < N; ++i) {
886     CE.Args.push_back(S->getArg(i));
887   }
888   return CE;
889 }
890 
891 CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
892   ASTContext &Ctx = FD->getASTContext();
893   LangOptions L = Ctx.getLangOpts();
894   RetainSummaryManager M(Ctx, L.ObjCAutoRefCount);
895   const RetainSummary *S = M.getFunctionSummary(FD);
896   CallEffects CE(S->getRetEffect());
897   unsigned N = FD->param_size();
898   for (unsigned i = 0; i < N; ++i) {
899     CE.Args.push_back(S->getArg(i));
900   }
901   return CE;
902 }
903