1//== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  This file defines summaries implementation for retain counting, which
10//  implements a reference count checker for Core Foundation, Cocoa
11//  and OSObject (on Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
16#include "clang/Analysis/RetainSummaryManager.h"
17#include "clang/AST/Attr.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/ParentMap.h"
21#include "clang/ASTMatchers/ASTMatchFinder.h"
22
23using namespace clang;
24using namespace ento;
25
26template <class T>
27constexpr static bool isOneOf() {
28  return false;
29}
30
31/// Helper function to check whether the class is one of the
32/// rest of varargs.
33template <class T, class P, class... ToCompare>
34constexpr static bool isOneOf() {
35  return std::is_same<T, P>::value || isOneOf<T, ToCompare...>();
36}
37
38namespace {
39
40/// Fake attribute class for RC* attributes.
41struct GeneralizedReturnsRetainedAttr {
42  static bool classof(const Attr *A) {
43    if (auto AA = dyn_cast<AnnotateAttr>(A))
44      return AA->getAnnotation() == "rc_ownership_returns_retained";
45    return false;
46  }
47};
48
49struct GeneralizedReturnsNotRetainedAttr {
50  static bool classof(const Attr *A) {
51    if (auto AA = dyn_cast<AnnotateAttr>(A))
52      return AA->getAnnotation() == "rc_ownership_returns_not_retained";
53    return false;
54  }
55};
56
57struct GeneralizedConsumedAttr {
58  static bool classof(const Attr *A) {
59    if (auto AA = dyn_cast<AnnotateAttr>(A))
60      return AA->getAnnotation() == "rc_ownership_consumed";
61    return false;
62  }
63};
64
65}
66
67template <class T>
68Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
69                                                            QualType QT) {
70  ObjKind K;
71  if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,
72              CFReturnsNotRetainedAttr>()) {
73    if (!TrackObjCAndCFObjects)
74      return None;
75
76    K = ObjKind::CF;
77  } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,
78                     NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,
79                     NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {
80
81    if (!TrackObjCAndCFObjects)
82      return None;
83
84    if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,
85                NSReturnsNotRetainedAttr>() &&
86        !cocoa::isCocoaObjectRef(QT))
87      return None;
88    K = ObjKind::ObjC;
89  } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,
90                     OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,
91                     OSReturnsRetainedOnZeroAttr,
92                     OSReturnsRetainedOnNonZeroAttr>()) {
93    if (!TrackOSObjects)
94      return None;
95    K = ObjKind::OS;
96  } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,
97                     GeneralizedReturnsRetainedAttr,
98                     GeneralizedConsumedAttr>()) {
99    K = ObjKind::Generalized;
100  } else {
101    llvm_unreachable("Unexpected attribute");
102  }
103  if (D->hasAttr<T>())
104    return K;
105  return None;
106}
107
108template <class T1, class T2, class... Others>
109Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
110                                                            QualType QT) {
111  if (auto Out = hasAnyEnabledAttrOf<T1>(D, QT))
112    return Out;
113  return hasAnyEnabledAttrOf<T2, Others...>(D, QT);
114}
115
116const RetainSummary *
117RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
118  // Unique "simple" summaries -- those without ArgEffects.
119  if (OldSumm.isSimple()) {
120    ::llvm::FoldingSetNodeID ID;
121    OldSumm.Profile(ID);
122
123    void *Pos;
124    CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
125
126    if (!N) {
127      N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
128      new (N) CachedSummaryNode(OldSumm);
129      SimpleSummaries.InsertNode(N, Pos);
130    }
131
132    return &N->getValue();
133  }
134
135  RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
136  new (Summ) RetainSummary(OldSumm);
137  return Summ;
138}
139
140static bool isSubclass(const Decl *D,
141                       StringRef ClassName) {
142  using namespace ast_matchers;
143  DeclarationMatcher SubclassM =
144      cxxRecordDecl(isSameOrDerivedFrom(std::string(ClassName)));
145  return !(match(SubclassM, *D, D->getASTContext()).empty());
146}
147
148static bool isOSObjectSubclass(const Decl *D) {
149  return D && isSubclass(D, "OSMetaClassBase");
150}
151
152static bool isOSObjectDynamicCast(StringRef S) {
153  return S == "safeMetaCast";
154}
155
156static bool isOSObjectRequiredCast(StringRef S) {
157  return S == "requiredMetaCast";
158}
159
160static bool isOSObjectThisCast(StringRef S) {
161  return S == "metaCast";
162}
163
164
165static bool isOSObjectPtr(QualType QT) {
166  return isOSObjectSubclass(QT->getPointeeCXXRecordDecl());
167}
168
169static bool isISLObjectRef(QualType Ty) {
170  return StringRef(Ty.getAsString()).startswith("isl_");
171}
172
173static bool isOSIteratorSubclass(const Decl *D) {
174  return isSubclass(D, "OSIterator");
175}
176
177static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
178  for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
179    if (Ann->getAnnotation() == rcAnnotation)
180      return true;
181  }
182  return false;
183}
184
185static bool isRetain(const FunctionDecl *FD, StringRef FName) {
186  return FName.startswith_lower("retain") || FName.endswith_lower("retain");
187}
188
189static bool isRelease(const FunctionDecl *FD, StringRef FName) {
190  return FName.startswith_lower("release") || FName.endswith_lower("release");
191}
192
193static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
194  return FName.startswith_lower("autorelease") ||
195         FName.endswith_lower("autorelease");
196}
197
198static bool isMakeCollectable(StringRef FName) {
199  return FName.contains_lower("MakeCollectable");
200}
201
202/// A function is OSObject related if it is declared on a subclass
203/// of OSObject, or any of the parameters is a subclass of an OSObject.
204static bool isOSObjectRelated(const CXXMethodDecl *MD) {
205  if (isOSObjectSubclass(MD->getParent()))
206    return true;
207
208  for (ParmVarDecl *Param : MD->parameters()) {
209    QualType PT = Param->getType()->getPointeeType();
210    if (!PT.isNull())
211      if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl())
212        if (isOSObjectSubclass(RD))
213          return true;
214  }
215
216  return false;
217}
218
219bool
220RetainSummaryManager::isKnownSmartPointer(QualType QT) {
221  QT = QT.getCanonicalType();
222  const auto *RD = QT->getAsCXXRecordDecl();
223  if (!RD)
224    return false;
225  const IdentifierInfo *II = RD->getIdentifier();
226  if (II && II->getName() == "smart_ptr")
227    if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()))
228      if (ND->getNameAsString() == "os")
229        return true;
230  return false;
231}
232
233const RetainSummary *
234RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,
235                                            StringRef FName, QualType RetTy) {
236  assert(TrackOSObjects &&
237         "Requesting a summary for an OSObject but OSObjects are not tracked");
238
239  if (RetTy->isPointerType()) {
240    const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
241    if (PD && isOSObjectSubclass(PD)) {
242      if (isOSObjectDynamicCast(FName) || isOSObjectRequiredCast(FName) ||
243          isOSObjectThisCast(FName))
244        return getDefaultSummary();
245
246      // TODO: Add support for the slightly common *Matching(table) idiom.
247      // Cf. IOService::nameMatching() etc. - these function have an unusual
248      // contract of returning at +0 or +1 depending on their last argument.
249      if (FName.endswith("Matching")) {
250        return getPersistentStopSummary();
251      }
252
253      // All objects returned with functions *not* starting with 'get',
254      // or iterators, are returned at +1.
255      if ((!FName.startswith("get") && !FName.startswith("Get")) ||
256          isOSIteratorSubclass(PD)) {
257        return getOSSummaryCreateRule(FD);
258      } else {
259        return getOSSummaryGetRule(FD);
260      }
261    }
262  }
263
264  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
265    const CXXRecordDecl *Parent = MD->getParent();
266    if (Parent && isOSObjectSubclass(Parent)) {
267      if (FName == "release" || FName == "taggedRelease")
268        return getOSSummaryReleaseRule(FD);
269
270      if (FName == "retain" || FName == "taggedRetain")
271        return getOSSummaryRetainRule(FD);
272
273      if (FName == "free")
274        return getOSSummaryFreeRule(FD);
275
276      if (MD->getOverloadedOperator() == OO_New)
277        return getOSSummaryCreateRule(MD);
278    }
279  }
280
281  return nullptr;
282}
283
284const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
285    const FunctionDecl *FD,
286    StringRef FName,
287    QualType RetTy,
288    const FunctionType *FT,
289    bool &AllowAnnotations) {
290
291  ArgEffects ScratchArgs(AF.getEmptyMap());
292
293  std::string RetTyName = RetTy.getAsString();
294  if (FName == "pthread_create" || FName == "pthread_setspecific") {
295    // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
296    // This will be addressed better with IPA.
297    return getPersistentStopSummary();
298  } else if(FName == "NSMakeCollectable") {
299    // Handle: id NSMakeCollectable(CFTypeRef)
300    AllowAnnotations = false;
301    return RetTy->isObjCIdType() ? getUnarySummary(FT, DoNothing)
302                                 : getPersistentStopSummary();
303  } else if (FName == "CMBufferQueueDequeueAndRetain" ||
304             FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
305    // Part of: <rdar://problem/39390714>.
306    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
307                                ScratchArgs,
308                                ArgEffect(DoNothing),
309                                ArgEffect(DoNothing));
310  } else if (FName == "CFPlugInInstanceCreate") {
311    return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs);
312  } else if (FName == "IORegistryEntrySearchCFProperty" ||
313             (RetTyName == "CFMutableDictionaryRef" &&
314              (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||
315               FName == "IOServiceNameMatching" ||
316               FName == "IORegistryEntryIDMatching" ||
317               FName == "IOOpenFirmwarePathMatching"))) {
318    // Part of <rdar://problem/6961230>. (IOKit)
319    // This should be addressed using a API table.
320    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
321                                ArgEffect(DoNothing), ArgEffect(DoNothing));
322  } else if (FName == "IOServiceGetMatchingService" ||
323             FName == "IOServiceGetMatchingServices") {
324    // FIXES: <rdar://problem/6326900>
325    // This should be addressed using a API table.  This strcmp is also
326    // a little gross, but there is no need to super optimize here.
327    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
328    return getPersistentSummary(RetEffect::MakeNoRet(),
329                                ScratchArgs,
330                                ArgEffect(DoNothing), ArgEffect(DoNothing));
331  } else if (FName == "IOServiceAddNotification" ||
332             FName == "IOServiceAddMatchingNotification") {
333    // Part of <rdar://problem/6961230>. (IOKit)
334    // This should be addressed using a API table.
335    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
336    return getPersistentSummary(RetEffect::MakeNoRet(),
337                                ScratchArgs,
338                                ArgEffect(DoNothing), ArgEffect(DoNothing));
339  } else if (FName == "CVPixelBufferCreateWithBytes") {
340    // FIXES: <rdar://problem/7283567>
341    // Eventually this can be improved by recognizing that the pixel
342    // buffer passed to CVPixelBufferCreateWithBytes is released via
343    // a callback and doing full IPA to make sure this is done correctly.
344    // FIXME: This function has an out parameter that returns an
345    // allocated object.
346    ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
347    return getPersistentSummary(RetEffect::MakeNoRet(),
348                                ScratchArgs,
349                                ArgEffect(DoNothing), ArgEffect(DoNothing));
350  } else if (FName == "CGBitmapContextCreateWithData") {
351    // FIXES: <rdar://problem/7358899>
352    // Eventually this can be improved by recognizing that 'releaseInfo'
353    // passed to CGBitmapContextCreateWithData is released via
354    // a callback and doing full IPA to make sure this is done correctly.
355    ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
356    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
357                                ArgEffect(DoNothing), ArgEffect(DoNothing));
358  } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
359    // FIXES: <rdar://problem/7283567>
360    // Eventually this can be improved by recognizing that the pixel
361    // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
362    // via a callback and doing full IPA to make sure this is done
363    // correctly.
364    ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
365    return getPersistentSummary(RetEffect::MakeNoRet(),
366                                ScratchArgs,
367                                ArgEffect(DoNothing), ArgEffect(DoNothing));
368  } else if (FName == "VTCompressionSessionEncodeFrame") {
369    // The context argument passed to VTCompressionSessionEncodeFrame()
370    // is passed to the callback specified when creating the session
371    // (e.g. with VTCompressionSessionCreate()) which can release it.
372    // To account for this possibility, conservatively stop tracking
373    // the context.
374    ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));
375    return getPersistentSummary(RetEffect::MakeNoRet(),
376                                ScratchArgs,
377                                ArgEffect(DoNothing), ArgEffect(DoNothing));
378  } else if (FName == "dispatch_set_context" ||
379             FName == "xpc_connection_set_context") {
380    // <rdar://problem/11059275> - The analyzer currently doesn't have
381    // a good way to reason about the finalizer function for libdispatch.
382    // If we pass a context object that is memory managed, stop tracking it.
383    // <rdar://problem/13783514> - Same problem, but for XPC.
384    // FIXME: this hack should possibly go away once we can handle
385    // libdispatch and XPC finalizers.
386    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
387    return getPersistentSummary(RetEffect::MakeNoRet(),
388                                ScratchArgs,
389                                ArgEffect(DoNothing), ArgEffect(DoNothing));
390  } else if (FName.startswith("NSLog")) {
391    return getDoNothingSummary();
392  } else if (FName.startswith("NS") &&
393             (FName.find("Insert") != StringRef::npos)) {
394    // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
395    // be deallocated by NSMapRemove. (radar://11152419)
396    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
397    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));
398    return getPersistentSummary(RetEffect::MakeNoRet(),
399                                ScratchArgs, ArgEffect(DoNothing),
400                                ArgEffect(DoNothing));
401  }
402
403  if (RetTy->isPointerType()) {
404
405    // For CoreFoundation ('CF') types.
406    if (cocoa::isRefType(RetTy, "CF", FName)) {
407      if (isRetain(FD, FName)) {
408        // CFRetain isn't supposed to be annotated. However, this may as
409        // well be a user-made "safe" CFRetain function that is incorrectly
410        // annotated as cf_returns_retained due to lack of better options.
411        // We want to ignore such annotation.
412        AllowAnnotations = false;
413
414        return getUnarySummary(FT, IncRef);
415      } else if (isAutorelease(FD, FName)) {
416        // The headers use cf_consumed, but we can fully model CFAutorelease
417        // ourselves.
418        AllowAnnotations = false;
419
420        return getUnarySummary(FT, Autorelease);
421      } else if (isMakeCollectable(FName)) {
422        AllowAnnotations = false;
423        return getUnarySummary(FT, DoNothing);
424      } else {
425        return getCFCreateGetRuleSummary(FD);
426      }
427    }
428
429    // For CoreGraphics ('CG') and CoreVideo ('CV') types.
430    if (cocoa::isRefType(RetTy, "CG", FName) ||
431        cocoa::isRefType(RetTy, "CV", FName)) {
432      if (isRetain(FD, FName))
433        return getUnarySummary(FT, IncRef);
434      else
435        return getCFCreateGetRuleSummary(FD);
436    }
437
438    // For all other CF-style types, use the Create/Get
439    // rule for summaries but don't support Retain functions
440    // with framework-specific prefixes.
441    if (coreFoundation::isCFObjectRef(RetTy)) {
442      return getCFCreateGetRuleSummary(FD);
443    }
444
445    if (FD->hasAttr<CFAuditedTransferAttr>()) {
446      return getCFCreateGetRuleSummary(FD);
447    }
448  }
449
450  // Check for release functions, the only kind of functions that we care
451  // about that don't return a pointer type.
452  if (FName.startswith("CG") || FName.startswith("CF")) {
453    // Test for 'CGCF'.
454    FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
455
456    if (isRelease(FD, FName))
457      return getUnarySummary(FT, DecRef);
458    else {
459      assert(ScratchArgs.isEmpty());
460      // Remaining CoreFoundation and CoreGraphics functions.
461      // We use to assume that they all strictly followed the ownership idiom
462      // and that ownership cannot be transferred.  While this is technically
463      // correct, many methods allow a tracked object to escape.  For example:
464      //
465      //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
466      //   CFDictionaryAddValue(y, key, x);
467      //   CFRelease(x);
468      //   ... it is okay to use 'x' since 'y' has a reference to it
469      //
470      // We handle this and similar cases with the follow heuristic.  If the
471      // function name contains "InsertValue", "SetValue", "AddValue",
472      // "AppendValue", or "SetAttribute", then we assume that arguments may
473      // "escape."  This means that something else holds on to the object,
474      // allowing it be used even after its local retain count drops to 0.
475      ArgEffectKind E =
476          (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
477           StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
478           StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
479           StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
480           StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
481              ? MayEscape
482              : DoNothing;
483
484      return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
485                                  ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF));
486    }
487  }
488
489  return nullptr;
490}
491
492const RetainSummary *
493RetainSummaryManager::generateSummary(const FunctionDecl *FD,
494                                      bool &AllowAnnotations) {
495  // We generate "stop" summaries for implicitly defined functions.
496  if (FD->isImplicit())
497    return getPersistentStopSummary();
498
499  const IdentifierInfo *II = FD->getIdentifier();
500
501  StringRef FName = II ? II->getName() : "";
502
503  // Strip away preceding '_'.  Doing this here will effect all the checks
504  // down below.
505  FName = FName.substr(FName.find_first_not_of('_'));
506
507  // Inspect the result type. Strip away any typedefs.
508  const auto *FT = FD->getType()->castAs<FunctionType>();
509  QualType RetTy = FT->getReturnType();
510
511  if (TrackOSObjects)
512    if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
513      return S;
514
515  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
516    if (!isOSObjectRelated(MD))
517      return getPersistentSummary(RetEffect::MakeNoRet(),
518                                  ArgEffects(AF.getEmptyMap()),
519                                  ArgEffect(DoNothing),
520                                  ArgEffect(StopTracking),
521                                  ArgEffect(DoNothing));
522
523  if (TrackObjCAndCFObjects)
524    if (const RetainSummary *S =
525            getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
526      return S;
527
528  return getDefaultSummary();
529}
530
531const RetainSummary *
532RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
533  // If we don't know what function we're calling, use our default summary.
534  if (!FD)
535    return getDefaultSummary();
536
537  // Look up a summary in our cache of FunctionDecls -> Summaries.
538  FuncSummariesTy::iterator I = FuncSummaries.find(FD);
539  if (I != FuncSummaries.end())
540    return I->second;
541
542  // No summary?  Generate one.
543  bool AllowAnnotations = true;
544  const RetainSummary *S = generateSummary(FD, AllowAnnotations);
545
546  // Annotations override defaults.
547  if (AllowAnnotations)
548    updateSummaryFromAnnotations(S, FD);
549
550  FuncSummaries[FD] = S;
551  return S;
552}
553
554//===----------------------------------------------------------------------===//
555// Summary creation for functions (largely uses of Core Foundation).
556//===----------------------------------------------------------------------===//
557
558static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
559  switch (E.getKind()) {
560  case DoNothing:
561  case Autorelease:
562  case DecRefBridgedTransferred:
563  case IncRef:
564  case UnretainedOutParameter:
565  case RetainedOutParameter:
566  case RetainedOutParameterOnZero:
567  case RetainedOutParameterOnNonZero:
568  case MayEscape:
569  case StopTracking:
570  case StopTrackingHard:
571    return E.withKind(StopTrackingHard);
572  case DecRef:
573  case DecRefAndStopTrackingHard:
574    return E.withKind(DecRefAndStopTrackingHard);
575  case Dealloc:
576    return E.withKind(Dealloc);
577  }
578
579  llvm_unreachable("Unknown ArgEffect kind");
580}
581
582const RetainSummary *
583RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
584                                                         AnyCall &C) {
585  ArgEffect RecEffect = getStopTrackingHardEquivalent(S->getReceiverEffect());
586  ArgEffect DefEffect = getStopTrackingHardEquivalent(S->getDefaultArgEffect());
587
588  ArgEffects ScratchArgs(AF.getEmptyMap());
589  ArgEffects CustomArgEffects = S->getArgEffects();
590  for (ArgEffects::iterator I = CustomArgEffects.begin(),
591                            E = CustomArgEffects.end();
592       I != E; ++I) {
593    ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
594    if (Translated.getKind() != DefEffect.getKind())
595      ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
596  }
597
598  RetEffect RE = RetEffect::MakeNoRetHard();
599
600  // Special cases where the callback argument CANNOT free the return value.
601  // This can generally only happen if we know that the callback will only be
602  // called when the return value is already being deallocated.
603  if (const IdentifierInfo *Name = C.getIdentifier()) {
604    // When the CGBitmapContext is deallocated, the callback here will free
605    // the associated data buffer.
606    // The callback in dispatch_data_create frees the buffer, but not
607    // the data object.
608    if (Name->isStr("CGBitmapContextCreateWithData") ||
609        Name->isStr("dispatch_data_create"))
610      RE = S->getRetEffect();
611  }
612
613  return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
614}
615
616void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(
617    const RetainSummary *&S) {
618
619  RetainSummaryTemplate Template(S, *this);
620
621  Template->setReceiverEffect(ArgEffect(DoNothing));
622  Template->setRetEffect(RetEffect::MakeNoRet());
623}
624
625
626void RetainSummaryManager::updateSummaryForArgumentTypes(
627  const AnyCall &C, const RetainSummary *&RS) {
628  RetainSummaryTemplate Template(RS, *this);
629
630  unsigned parm_idx = 0;
631  for (auto pi = C.param_begin(), pe = C.param_end(); pi != pe;
632       ++pi, ++parm_idx) {
633    QualType QT = (*pi)->getType();
634
635    // Skip already created values.
636    if (RS->getArgEffects().contains(parm_idx))
637      continue;
638
639    ObjKind K = ObjKind::AnyObj;
640
641    if (isISLObjectRef(QT)) {
642      K = ObjKind::Generalized;
643    } else if (isOSObjectPtr(QT)) {
644      K = ObjKind::OS;
645    } else if (cocoa::isCocoaObjectRef(QT)) {
646      K = ObjKind::ObjC;
647    } else if (coreFoundation::isCFObjectRef(QT)) {
648      K = ObjKind::CF;
649    }
650
651    if (K != ObjKind::AnyObj)
652      Template->addArg(AF, parm_idx,
653                       ArgEffect(RS->getDefaultArgEffect().getKind(), K));
654  }
655}
656
657const RetainSummary *
658RetainSummaryManager::getSummary(AnyCall C,
659                                 bool HasNonZeroCallbackArg,
660                                 bool IsReceiverUnconsumedSelf,
661                                 QualType ReceiverType) {
662  const RetainSummary *Summ;
663  switch (C.getKind()) {
664  case AnyCall::Function:
665  case AnyCall::Constructor:
666  case AnyCall::InheritedConstructor:
667  case AnyCall::Allocator:
668  case AnyCall::Deallocator:
669    Summ = getFunctionSummary(cast_or_null<FunctionDecl>(C.getDecl()));
670    break;
671  case AnyCall::Block:
672  case AnyCall::Destructor:
673    // FIXME: These calls are currently unsupported.
674    return getPersistentStopSummary();
675  case AnyCall::ObjCMethod: {
676    const auto *ME = cast_or_null<ObjCMessageExpr>(C.getExpr());
677    if (!ME) {
678      Summ = getMethodSummary(cast<ObjCMethodDecl>(C.getDecl()));
679    } else if (ME->isInstanceMessage()) {
680      Summ = getInstanceMethodSummary(ME, ReceiverType);
681    } else {
682      Summ = getClassMethodSummary(ME);
683    }
684    break;
685  }
686  }
687
688  if (HasNonZeroCallbackArg)
689    Summ = updateSummaryForNonZeroCallbackArg(Summ, C);
690
691  if (IsReceiverUnconsumedSelf)
692    updateSummaryForReceiverUnconsumedSelf(Summ);
693
694  updateSummaryForArgumentTypes(C, Summ);
695
696  assert(Summ && "Unknown call type?");
697  return Summ;
698}
699
700
701const RetainSummary *
702RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
703  if (coreFoundation::followsCreateRule(FD))
704    return getCFSummaryCreateRule(FD);
705
706  return getCFSummaryGetRule(FD);
707}
708
709bool RetainSummaryManager::isTrustedReferenceCountImplementation(
710    const Decl *FD) {
711  return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
712}
713
714Optional<RetainSummaryManager::BehaviorSummary>
715RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
716                              bool &hasTrustedImplementationAnnotation) {
717
718  IdentifierInfo *II = FD->getIdentifier();
719  if (!II)
720    return None;
721
722  StringRef FName = II->getName();
723  FName = FName.substr(FName.find_first_not_of('_'));
724
725  QualType ResultTy = CE->getCallReturnType(Ctx);
726  if (ResultTy->isObjCIdType()) {
727    if (II->isStr("NSMakeCollectable"))
728      return BehaviorSummary::Identity;
729  } else if (ResultTy->isPointerType()) {
730    // Handle: (CF|CG|CV)Retain
731    //         CFAutorelease
732    // It's okay to be a little sloppy here.
733    if (FName == "CMBufferQueueDequeueAndRetain" ||
734        FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
735      // Part of: <rdar://problem/39390714>.
736      // These are not retain. They just return something and retain it.
737      return None;
738    }
739    if (CE->getNumArgs() == 1 &&
740        (cocoa::isRefType(ResultTy, "CF", FName) ||
741         cocoa::isRefType(ResultTy, "CG", FName) ||
742         cocoa::isRefType(ResultTy, "CV", FName)) &&
743        (isRetain(FD, FName) || isAutorelease(FD, FName) ||
744         isMakeCollectable(FName)))
745      return BehaviorSummary::Identity;
746
747    // safeMetaCast is called by OSDynamicCast.
748    // We assume that OSDynamicCast is either an identity (cast is OK,
749    // the input was non-zero),
750    // or that it returns zero (when the cast failed, or the input
751    // was zero).
752    if (TrackOSObjects) {
753      if (isOSObjectDynamicCast(FName) && FD->param_size() >= 1) {
754        return BehaviorSummary::IdentityOrZero;
755      } else if (isOSObjectRequiredCast(FName) && FD->param_size() >= 1) {
756        return BehaviorSummary::Identity;
757      } else if (isOSObjectThisCast(FName) && isa<CXXMethodDecl>(FD) &&
758                 !cast<CXXMethodDecl>(FD)->isStatic()) {
759        return BehaviorSummary::IdentityThis;
760      }
761    }
762
763    const FunctionDecl* FDD = FD->getDefinition();
764    if (FDD && isTrustedReferenceCountImplementation(FDD)) {
765      hasTrustedImplementationAnnotation = true;
766      return BehaviorSummary::Identity;
767    }
768  }
769
770  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
771    const CXXRecordDecl *Parent = MD->getParent();
772    if (TrackOSObjects && Parent && isOSObjectSubclass(Parent))
773      if (FName == "release" || FName == "retain")
774        return BehaviorSummary::NoOp;
775  }
776
777  return None;
778}
779
780const RetainSummary *
781RetainSummaryManager::getUnarySummary(const FunctionType* FT,
782                                      ArgEffectKind AE) {
783
784  // Unary functions have no arg effects by definition.
785  ArgEffects ScratchArgs(AF.getEmptyMap());
786
787  // Sanity check that this is *really* a unary function.  This can
788  // happen if people do weird things.
789  const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
790  if (!FTP || FTP->getNumParams() != 1)
791    return getPersistentStopSummary();
792
793  ArgEffect Effect(AE, ObjKind::CF);
794
795  ScratchArgs = AF.add(ScratchArgs, 0, Effect);
796  return getPersistentSummary(RetEffect::MakeNoRet(),
797                              ScratchArgs,
798                              ArgEffect(DoNothing), ArgEffect(DoNothing));
799}
800
801const RetainSummary *
802RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {
803  return getPersistentSummary(RetEffect::MakeNoRet(),
804                              AF.getEmptyMap(),
805                              /*ReceiverEff=*/ArgEffect(DoNothing),
806                              /*DefaultEff=*/ArgEffect(DoNothing),
807                              /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS));
808}
809
810const RetainSummary *
811RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {
812  return getPersistentSummary(RetEffect::MakeNoRet(),
813                              AF.getEmptyMap(),
814                              /*ReceiverEff=*/ArgEffect(DoNothing),
815                              /*DefaultEff=*/ArgEffect(DoNothing),
816                              /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS));
817}
818
819const RetainSummary *
820RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {
821  return getPersistentSummary(RetEffect::MakeNoRet(),
822                              AF.getEmptyMap(),
823                              /*ReceiverEff=*/ArgEffect(DoNothing),
824                              /*DefaultEff=*/ArgEffect(DoNothing),
825                              /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS));
826}
827
828const RetainSummary *
829RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) {
830  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::OS),
831                              AF.getEmptyMap());
832}
833
834const RetainSummary *
835RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) {
836  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::OS),
837                              AF.getEmptyMap());
838}
839
840const RetainSummary *
841RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
842  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
843                              ArgEffects(AF.getEmptyMap()));
844}
845
846const RetainSummary *
847RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
848  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF),
849                              ArgEffects(AF.getEmptyMap()),
850                              ArgEffect(DoNothing), ArgEffect(DoNothing));
851}
852
853
854
855
856//===----------------------------------------------------------------------===//
857// Summary creation for Selectors.
858//===----------------------------------------------------------------------===//
859
860Optional<RetEffect>
861RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
862                                                  const Decl *D) {
863  if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy))
864    return ObjCAllocRetE;
865
866  if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,
867                                   GeneralizedReturnsRetainedAttr>(D, RetTy))
868    return RetEffect::MakeOwned(*K);
869
870  if (auto K = hasAnyEnabledAttrOf<
871          CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,
872          GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,
873          NSReturnsAutoreleasedAttr>(D, RetTy))
874    return RetEffect::MakeNotOwned(*K);
875
876  if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
877    for (const auto *PD : MD->overridden_methods())
878      if (auto RE = getRetEffectFromAnnotations(RetTy, PD))
879        return RE;
880
881  return None;
882}
883
884/// \return Whether the chain of typedefs starting from @c QT
885/// has a typedef with a given name @c Name.
886static bool hasTypedefNamed(QualType QT,
887                            StringRef Name) {
888  while (auto *T = dyn_cast<TypedefType>(QT)) {
889    const auto &Context = T->getDecl()->getASTContext();
890    if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name))
891      return true;
892    QT = T->getDecl()->getUnderlyingType();
893  }
894  return false;
895}
896
897static QualType getCallableReturnType(const NamedDecl *ND) {
898  if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
899    return FD->getReturnType();
900  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) {
901    return MD->getReturnType();
902  } else {
903    llvm_unreachable("Unexpected decl");
904  }
905}
906
907bool RetainSummaryManager::applyParamAnnotationEffect(
908    const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD,
909    RetainSummaryTemplate &Template) {
910  QualType QT = pd->getType();
911  if (auto K =
912          hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,
913                              GeneralizedConsumedAttr>(pd, QT)) {
914    Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K));
915    return true;
916  } else if (auto K = hasAnyEnabledAttrOf<
917                 CFReturnsRetainedAttr, OSReturnsRetainedAttr,
918                 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,
919                 GeneralizedReturnsRetainedAttr>(pd, QT)) {
920
921    // For OSObjects, we try to guess whether the object is created based
922    // on the return value.
923    if (K == ObjKind::OS) {
924      QualType QT = getCallableReturnType(FD);
925
926      bool HasRetainedOnZero = pd->hasAttr<OSReturnsRetainedOnZeroAttr>();
927      bool HasRetainedOnNonZero = pd->hasAttr<OSReturnsRetainedOnNonZeroAttr>();
928
929      // The usual convention is to create an object on non-zero return, but
930      // it's reverted if the typedef chain has a typedef kern_return_t,
931      // because kReturnSuccess constant is defined as zero.
932      // The convention can be overwritten by custom attributes.
933      bool SuccessOnZero =
934          HasRetainedOnZero ||
935          (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero);
936      bool ShouldSplit = !QT.isNull() && !QT->isVoidType();
937      ArgEffectKind AK = RetainedOutParameter;
938      if (ShouldSplit && SuccessOnZero) {
939        AK = RetainedOutParameterOnZero;
940      } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {
941        AK = RetainedOutParameterOnNonZero;
942      }
943      Template->addArg(AF, parm_idx, ArgEffect(AK, ObjKind::OS));
944    }
945
946    // For others:
947    // Do nothing. Retained out parameters will either point to a +1 reference
948    // or NULL, but the way you check for failure differs depending on the
949    // API. Consequently, we don't have a good way to track them yet.
950    return true;
951  } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,
952                                          OSReturnsNotRetainedAttr,
953                                          GeneralizedReturnsNotRetainedAttr>(
954                 pd, QT)) {
955    Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter, *K));
956    return true;
957  }
958
959  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
960    for (const auto *OD : MD->overridden_methods()) {
961      const ParmVarDecl *OP = OD->parameters()[parm_idx];
962      if (applyParamAnnotationEffect(OP, parm_idx, OD, Template))
963        return true;
964    }
965  }
966
967  return false;
968}
969
970void
971RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
972                                                   const FunctionDecl *FD) {
973  if (!FD)
974    return;
975
976  assert(Summ && "Must have a summary to add annotations to.");
977  RetainSummaryTemplate Template(Summ, *this);
978
979  // Effects on the parameters.
980  unsigned parm_idx = 0;
981  for (auto pi = FD->param_begin(),
982         pe = FD->param_end(); pi != pe; ++pi, ++parm_idx)
983    applyParamAnnotationEffect(*pi, parm_idx, FD, Template);
984
985  QualType RetTy = FD->getReturnType();
986  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
987    Template->setRetEffect(*RetE);
988
989  if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy))
990    Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS));
991}
992
993void
994RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
995                                                   const ObjCMethodDecl *MD) {
996  if (!MD)
997    return;
998
999  assert(Summ && "Must have a valid summary to add annotations to");
1000  RetainSummaryTemplate Template(Summ, *this);
1001
1002  // Effects on the receiver.
1003  if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->getReturnType()))
1004    Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC));
1005
1006  // Effects on the parameters.
1007  unsigned parm_idx = 0;
1008  for (auto pi = MD->param_begin(), pe = MD->param_end(); pi != pe;
1009       ++pi, ++parm_idx)
1010    applyParamAnnotationEffect(*pi, parm_idx, MD, Template);
1011
1012  QualType RetTy = MD->getReturnType();
1013  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
1014    Template->setRetEffect(*RetE);
1015}
1016
1017const RetainSummary *
1018RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
1019                                               Selector S, QualType RetTy) {
1020  // Any special effects?
1021  ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC);
1022  RetEffect ResultEff = RetEffect::MakeNoRet();
1023
1024  // Check the method family, and apply any default annotations.
1025  switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
1026    case OMF_None:
1027    case OMF_initialize:
1028    case OMF_performSelector:
1029      // Assume all Objective-C methods follow Cocoa Memory Management rules.
1030      // FIXME: Does the non-threaded performSelector family really belong here?
1031      // The selector could be, say, @selector(copy).
1032      if (cocoa::isCocoaObjectRef(RetTy))
1033        ResultEff = RetEffect::MakeNotOwned(ObjKind::ObjC);
1034      else if (coreFoundation::isCFObjectRef(RetTy)) {
1035        // ObjCMethodDecl currently doesn't consider CF objects as valid return
1036        // values for alloc, new, copy, or mutableCopy, so we have to
1037        // double-check with the selector. This is ugly, but there aren't that
1038        // many Objective-C methods that return CF objects, right?
1039        if (MD) {
1040          switch (S.getMethodFamily()) {
1041          case OMF_alloc:
1042          case OMF_new:
1043          case OMF_copy:
1044          case OMF_mutableCopy:
1045            ResultEff = RetEffect::MakeOwned(ObjKind::CF);
1046            break;
1047          default:
1048            ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
1049            break;
1050          }
1051        } else {
1052          ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
1053        }
1054      }
1055      break;
1056    case OMF_init:
1057      ResultEff = ObjCInitRetE;
1058      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
1059      break;
1060    case OMF_alloc:
1061    case OMF_new:
1062    case OMF_copy:
1063    case OMF_mutableCopy:
1064      if (cocoa::isCocoaObjectRef(RetTy))
1065        ResultEff = ObjCAllocRetE;
1066      else if (coreFoundation::isCFObjectRef(RetTy))
1067        ResultEff = RetEffect::MakeOwned(ObjKind::CF);
1068      break;
1069    case OMF_autorelease:
1070      ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC);
1071      break;
1072    case OMF_retain:
1073      ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC);
1074      break;
1075    case OMF_release:
1076      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
1077      break;
1078    case OMF_dealloc:
1079      ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC);
1080      break;
1081    case OMF_self:
1082      // -self is handled specially by the ExprEngine to propagate the receiver.
1083      break;
1084    case OMF_retainCount:
1085    case OMF_finalize:
1086      // These methods don't return objects.
1087      break;
1088  }
1089
1090  // If one of the arguments in the selector has the keyword 'delegate' we
1091  // should stop tracking the reference count for the receiver.  This is
1092  // because the reference count is quite possibly handled by a delegate
1093  // method.
1094  if (S.isKeywordSelector()) {
1095    for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
1096      StringRef Slot = S.getNameForSlot(i);
1097      if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
1098        if (ResultEff == ObjCInitRetE)
1099          ResultEff = RetEffect::MakeNoRetHard();
1100        else
1101          ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC);
1102      }
1103    }
1104  }
1105
1106  if (ReceiverEff.getKind() == DoNothing &&
1107      ResultEff.getKind() == RetEffect::NoRet)
1108    return getDefaultSummary();
1109
1110  return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),
1111                              ArgEffect(ReceiverEff), ArgEffect(MayEscape));
1112}
1113
1114const RetainSummary *
1115RetainSummaryManager::getClassMethodSummary(const ObjCMessageExpr *ME) {
1116  assert(!ME->isInstanceMessage());
1117  const ObjCInterfaceDecl *Class = ME->getReceiverInterface();
1118
1119  return getMethodSummary(ME->getSelector(), Class, ME->getMethodDecl(),
1120                          ME->getType(), ObjCClassMethodSummaries);
1121}
1122
1123const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
1124    const ObjCMessageExpr *ME,
1125    QualType ReceiverType) {
1126  const ObjCInterfaceDecl *ReceiverClass = nullptr;
1127
1128  // We do better tracking of the type of the object than the core ExprEngine.
1129  // See if we have its type in our private state.
1130  if (!ReceiverType.isNull())
1131    if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
1132      ReceiverClass = PT->getInterfaceDecl();
1133
1134  // If we don't know what kind of object this is, fall back to its static type.
1135  if (!ReceiverClass)
1136    ReceiverClass = ME->getReceiverInterface();
1137
1138  // FIXME: The receiver could be a reference to a class, meaning that
1139  //  we should use the class method.
1140  // id x = [NSObject class];
1141  // [x performSelector:... withObject:... afterDelay:...];
1142  Selector S = ME->getSelector();
1143  const ObjCMethodDecl *Method = ME->getMethodDecl();
1144  if (!Method && ReceiverClass)
1145    Method = ReceiverClass->getInstanceMethod(S);
1146
1147  return getMethodSummary(S, ReceiverClass, Method, ME->getType(),
1148                          ObjCMethodSummaries);
1149}
1150
1151const RetainSummary *
1152RetainSummaryManager::getMethodSummary(Selector S,
1153                                       const ObjCInterfaceDecl *ID,
1154                                       const ObjCMethodDecl *MD, QualType RetTy,
1155                                       ObjCMethodSummariesTy &CachedSummaries) {
1156
1157  // Objective-C method summaries are only applicable to ObjC and CF objects.
1158  if (!TrackObjCAndCFObjects)
1159    return getDefaultSummary();
1160
1161  // Look up a summary in our summary cache.
1162  const RetainSummary *Summ = CachedSummaries.find(ID, S);
1163
1164  if (!Summ) {
1165    Summ = getStandardMethodSummary(MD, S, RetTy);
1166
1167    // Annotations override defaults.
1168    updateSummaryFromAnnotations(Summ, MD);
1169
1170    // Memoize the summary.
1171    CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1172  }
1173
1174  return Summ;
1175}
1176
1177void RetainSummaryManager::InitializeClassMethodSummaries() {
1178  ArgEffects ScratchArgs = AF.getEmptyMap();
1179
1180  // Create the [NSAssertionHandler currentHander] summary.
1181  addClassMethSummary("NSAssertionHandler", "currentHandler",
1182                getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::ObjC),
1183                                     ScratchArgs));
1184
1185  // Create the [NSAutoreleasePool addObject:] summary.
1186  ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));
1187  addClassMethSummary("NSAutoreleasePool", "addObject",
1188                      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
1189                                           ArgEffect(DoNothing),
1190                                           ArgEffect(Autorelease)));
1191}
1192
1193void RetainSummaryManager::InitializeMethodSummaries() {
1194
1195  ArgEffects ScratchArgs = AF.getEmptyMap();
1196  // Create the "init" selector.  It just acts as a pass-through for the
1197  // receiver.
1198  const RetainSummary *InitSumm = getPersistentSummary(
1199      ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC));
1200  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
1201
1202  // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
1203  // claims the receiver and returns a retained object.
1204  addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
1205                         InitSumm);
1206
1207  // The next methods are allocators.
1208  const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,
1209                                                        ScratchArgs);
1210  const RetainSummary *CFAllocSumm =
1211    getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs);
1212
1213  // Create the "retain" selector.
1214  RetEffect NoRet = RetEffect::MakeNoRet();
1215  const RetainSummary *Summ = getPersistentSummary(
1216      NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC));
1217  addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
1218
1219  // Create the "release" selector.
1220  Summ = getPersistentSummary(NoRet, ScratchArgs,
1221                              ArgEffect(DecRef, ObjKind::ObjC));
1222  addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
1223
1224  // Create the -dealloc summary.
1225  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc,
1226                                                            ObjKind::ObjC));
1227  addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
1228
1229  // Create the "autorelease" selector.
1230  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease,
1231                                                            ObjKind::ObjC));
1232  addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
1233
1234  // For NSWindow, allocated objects are (initially) self-owned.
1235  // FIXME: For now we opt for false negatives with NSWindow, as these objects
1236  //  self-own themselves.  However, they only do this once they are displayed.
1237  //  Thus, we need to track an NSWindow's display status.
1238  //  This is tracked in <rdar://problem/6062711>.
1239  //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
1240  const RetainSummary *NoTrackYet =
1241      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
1242                           ArgEffect(StopTracking), ArgEffect(StopTracking));
1243
1244  addClassMethSummary("NSWindow", "alloc", NoTrackYet);
1245
1246  // For NSPanel (which subclasses NSWindow), allocated objects are not
1247  //  self-owned.
1248  // FIXME: For now we don't track NSPanels. object for the same reason
1249  //   as for NSWindow objects.
1250  addClassMethSummary("NSPanel", "alloc", NoTrackYet);
1251
1252  // For NSNull, objects returned by +null are singletons that ignore
1253  // retain/release semantics.  Just don't track them.
1254  // <rdar://problem/12858915>
1255  addClassMethSummary("NSNull", "null", NoTrackYet);
1256
1257  // Don't track allocated autorelease pools, as it is okay to prematurely
1258  // exit a method.
1259  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
1260  addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
1261  addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
1262
1263  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
1264  addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
1265  addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
1266
1267  // Create summaries for CIContext, 'createCGImage' and
1268  // 'createCGLayerWithSize'.  These objects are CF objects, and are not
1269  // automatically garbage collected.
1270  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
1271  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
1272                     "format", "colorSpace");
1273  addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
1274}
1275
1276const RetainSummary *
1277RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {
1278  const ObjCInterfaceDecl *ID = MD->getClassInterface();
1279  Selector S = MD->getSelector();
1280  QualType ResultTy = MD->getReturnType();
1281
1282  ObjCMethodSummariesTy *CachedSummaries;
1283  if (MD->isInstanceMethod())
1284    CachedSummaries = &ObjCMethodSummaries;
1285  else
1286    CachedSummaries = &ObjCClassMethodSummaries;
1287
1288  return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
1289}
1290