Clang Project

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