23 using namespace clang;
33 template <
class T,
class P,
class... ToCompare>
35 return std::is_same<T, P>::value ||
isOneOf<T, ToCompare...>();
41 struct GeneralizedReturnsRetainedAttr {
42 static bool classof(
const Attr *A) {
43 if (
auto AA = dyn_cast<AnnotateAttr>(A))
44 return AA->getAnnotation() ==
"rc_ownership_returns_retained";
49 struct 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";
57 struct GeneralizedConsumedAttr {
58 static bool classof(
const Attr *A) {
59 if (
auto AA = dyn_cast<AnnotateAttr>(A))
60 return AA->getAnnotation() ==
"rc_ownership_consumed";
71 if (
isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,
72 CFReturnsNotRetainedAttr>()) {
73 if (!TrackObjCAndCFObjects)
77 }
else if (
isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,
78 NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,
79 NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {
81 if (!TrackObjCAndCFObjects)
84 if (
isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,
85 NSReturnsNotRetainedAttr>() &&
89 }
else if (
isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,
90 OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,
91 OSReturnsRetainedOnZeroAttr,
92 OSReturnsRetainedOnNonZeroAttr>()) {
96 }
else if (
isOneOf<T, GeneralizedReturnsNotRetainedAttr,
97 GeneralizedReturnsRetainedAttr,
98 GeneralizedConsumedAttr>()) {
101 llvm_unreachable(
"Unexpected attribute");
108 template <
class T1,
class T2,
class... Others>
111 if (
auto Out = hasAnyEnabledAttrOf<T1>(D, QT))
113 return hasAnyEnabledAttrOf<T2, Others...>(D, QT);
117 RetainSummaryManager::getPersistentSummary(
const RetainSummary &OldSumm) {
120 ::llvm::FoldingSetNodeID
ID;
124 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(
ID, Pos);
127 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
128 new (N) CachedSummaryNode(OldSumm);
129 SimpleSummaries.InsertNode(N, Pos);
132 return &N->getValue();
141 StringRef ClassName) {
142 using namespace ast_matchers;
153 return S ==
"safeMetaCast";
157 return S ==
"requiredMetaCast";
161 return S ==
"metaCast";
170 return StringRef(Ty.
getAsString()).startswith(
"isl_");
179 if (Ann->getAnnotation() == rcAnnotation)
186 return FName.startswith_lower(
"retain") || FName.endswith_lower(
"retain");
190 return FName.startswith_lower(
"release") || FName.endswith_lower(
"release");
194 return FName.startswith_lower(
"autorelease") ||
195 FName.endswith_lower(
"autorelease");
199 return FName.contains_lower(
"MakeCollectable");
226 if (II && II->
getName() ==
"smart_ptr")
227 if (
const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()))
228 if (ND->getNameAsString() ==
"os")
234 RetainSummaryManager::getSummaryForOSObject(
const FunctionDecl *FD,
236 assert(TrackOSObjects &&
237 "Requesting a summary for an OSObject but OSObjects are not tracked");
244 return getDefaultSummary();
249 if (FName.endswith(
"Matching")) {
250 return getPersistentStopSummary();
255 if ((!FName.startswith(
"get") && !FName.startswith(
"Get")) ||
257 return getOSSummaryCreateRule(FD);
259 return getOSSummaryGetRule(FD);
264 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
267 if (FName ==
"release" || FName ==
"taggedRelease")
268 return getOSSummaryReleaseRule(FD);
270 if (FName ==
"retain" || FName ==
"taggedRetain")
271 return getOSSummaryRetainRule(FD);
274 return getOSSummaryFreeRule(FD);
276 if (MD->getOverloadedOperator() == OO_New)
277 return getOSSummaryCreateRule(MD);
284 const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
289 bool &AllowAnnotations) {
294 if (FName ==
"pthread_create" || FName ==
"pthread_setspecific") {
297 return getPersistentStopSummary();
298 }
else if(FName ==
"NSMakeCollectable") {
300 AllowAnnotations =
false;
302 : getPersistentStopSummary();
303 }
else if (FName ==
"CMBufferQueueDequeueAndRetain" ||
304 FName ==
"CMBufferQueueDequeueIfDataReadyAndRetain") {
310 }
else if (FName ==
"CFPlugInInstanceCreate") {
312 }
else if (FName ==
"IORegistryEntrySearchCFProperty" ||
313 (RetTyName ==
"CFMutableDictionaryRef" &&
314 (FName ==
"IOBSDNameMatching" || FName ==
"IOServiceMatching" ||
315 FName ==
"IOServiceNameMatching" ||
316 FName ==
"IORegistryEntryIDMatching" ||
317 FName ==
"IOOpenFirmwarePathMatching"))) {
322 }
else if (FName ==
"IOServiceGetMatchingService" ||
323 FName ==
"IOServiceGetMatchingServices") {
331 }
else if (FName ==
"IOServiceAddNotification" ||
332 FName ==
"IOServiceAddMatchingNotification") {
339 }
else if (FName ==
"CVPixelBufferCreateWithBytes") {
350 }
else if (FName ==
"CGBitmapContextCreateWithData") {
358 }
else if (FName ==
"CVPixelBufferCreateWithPlanarBytes") {
368 }
else if (FName ==
"VTCompressionSessionEncodeFrame") {
378 }
else if (FName ==
"dispatch_set_context" ||
379 FName ==
"xpc_connection_set_context") {
390 }
else if (FName.startswith(
"NSLog")) {
391 return getDoNothingSummary();
392 }
else if (FName.startswith(
"NS") &&
393 (FName.find(
"Insert") != StringRef::npos)) {
412 AllowAnnotations =
false;
414 return getUnarySummary(FT,
IncRef);
418 AllowAnnotations =
false;
422 AllowAnnotations =
false;
425 return getCFCreateGetRuleSummary(FD);
433 return getUnarySummary(FT,
IncRef);
435 return getCFCreateGetRuleSummary(FD);
442 return getCFCreateGetRuleSummary(FD);
445 if (FD->
hasAttr<CFAuditedTransferAttr>()) {
446 return getCFCreateGetRuleSummary(FD);
452 if (FName.startswith(
"CG") || FName.startswith(
"CF")) {
454 FName = FName.substr(FName.startswith(
"CGCF") ? 4 : 2);
457 return getUnarySummary(FT,
DecRef);
459 assert(ScratchArgs.isEmpty());
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)
493 RetainSummaryManager::generateSummary(
const FunctionDecl *FD,
494 bool &AllowAnnotations) {
497 return getPersistentStopSummary();
501 StringRef FName = II ? II->
getName() :
"";
505 FName = FName.substr(FName.find_first_not_of(
'_'));
512 if (
const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
515 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD))
523 if (TrackObjCAndCFObjects)
525 getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
528 return getDefaultSummary();
532 RetainSummaryManager::getFunctionSummary(
const FunctionDecl *FD) {
535 return getDefaultSummary();
538 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
539 if (I != FuncSummaries.end())
543 bool AllowAnnotations =
true;
544 const RetainSummary *S = generateSummary(FD, AllowAnnotations);
547 if (AllowAnnotations)
548 updateSummaryFromAnnotations(S, FD);
550 FuncSummaries[FD] = S;
579 llvm_unreachable(
"Unknown ArgEffect kind");
583 RetainSummaryManager::updateSummaryForNonZeroCallbackArg(
const RetainSummary *S,
589 ArgEffects CustomArgEffects = S->getArgEffects();
590 for (ArgEffects::iterator I = CustomArgEffects.begin(),
591 E = CustomArgEffects.end();
595 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
608 if (Name->isStr(
"CGBitmapContextCreateWithData") ||
609 Name->isStr(
"dispatch_data_create"))
610 RE = S->getRetEffect();
613 return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
616 void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(
626 void RetainSummaryManager::updateSummaryForArgumentTypes(
630 unsigned parm_idx = 0;
631 for (
auto pi =
C.param_begin(), pe =
C.param_end(); pi != pe;
652 Template->addArg(AF, parm_idx,
659 bool HasNonZeroCallbackArg,
660 bool IsReceiverUnconsumedSelf,
663 switch (C.getKind()) {
669 Summ = getFunctionSummary(cast_or_null<FunctionDecl>(C.getDecl()));
674 return getPersistentStopSummary();
676 const auto *ME = cast_or_null<ObjCMessageExpr>(C.getExpr());
678 Summ = getMethodSummary(cast<ObjCMethodDecl>(C.getDecl()));
679 }
else if (ME->isInstanceMessage()) {
680 Summ = getInstanceMethodSummary(ME, ReceiverType);
682 Summ = getClassMethodSummary(ME);
688 if (HasNonZeroCallbackArg)
689 Summ = updateSummaryForNonZeroCallbackArg(Summ, C);
691 if (IsReceiverUnconsumedSelf)
692 updateSummaryForReceiverUnconsumedSelf(Summ);
694 updateSummaryForArgumentTypes(C, Summ);
696 assert(Summ &&
"Unknown call type?");
702 RetainSummaryManager::getCFCreateGetRuleSummary(
const FunctionDecl *FD) {
704 return getCFSummaryCreateRule(FD);
706 return getCFSummaryGetRule(FD);
716 bool &hasTrustedImplementationAnnotation) {
722 StringRef FName = II->
getName();
723 FName = FName.substr(FName.find_first_not_of(
'_'));
727 if (II->
isStr(
"NSMakeCollectable"))
733 if (FName ==
"CMBufferQueueDequeueAndRetain" ||
734 FName ==
"CMBufferQueueDequeueIfDataReadyAndRetain") {
752 if (TrackOSObjects) {
758 !cast<CXXMethodDecl>(FD)->isStatic()) {
765 hasTrustedImplementationAnnotation =
true;
770 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
773 if (FName ==
"release" || FName ==
"retain")
781 RetainSummaryManager::getUnarySummary(
const FunctionType* FT,
791 return getPersistentStopSummary();
795 ScratchArgs = AF.add(ScratchArgs, 0, Effect);
802 RetainSummaryManager::getOSSummaryRetainRule(
const FunctionDecl *FD) {
811 RetainSummaryManager::getOSSummaryReleaseRule(
const FunctionDecl *FD) {
820 RetainSummaryManager::getOSSummaryFreeRule(
const FunctionDecl *FD) {
829 RetainSummaryManager::getOSSummaryCreateRule(
const FunctionDecl *FD) {
835 RetainSummaryManager::getOSSummaryGetRule(
const FunctionDecl *FD) {
841 RetainSummaryManager::getCFSummaryCreateRule(
const FunctionDecl *FD) {
847 RetainSummaryManager::getCFSummaryGetRule(
const FunctionDecl *FD) {
861 RetainSummaryManager::getRetEffectFromAnnotations(
QualType RetTy,
863 if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy))
864 return ObjCAllocRetE;
866 if (
auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,
867 GeneralizedReturnsRetainedAttr>(D, RetTy))
870 if (
auto K = hasAnyEnabledAttrOf<
871 CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,
872 GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,
873 NSReturnsAutoreleasedAttr>(D, RetTy))
876 if (
const auto *MD = dyn_cast<CXXMethodDecl>(D))
877 for (
const auto *PD : MD->overridden_methods())
878 if (
auto RE = getRetEffectFromAnnotations(RetTy, PD))
888 while (
auto *T = dyn_cast<TypedefType>(QT)) {
889 const auto &Context = T->getDecl()->getASTContext();
890 if (T->getDecl()->getIdentifier() == &Context.
Idents.
get(Name))
892 QT = T->getDecl()->getUnderlyingType();
898 if (
const auto *FD = dyn_cast<FunctionDecl>(ND)) {
900 }
else if (
const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) {
901 return MD->getReturnType();
903 llvm_unreachable(
"Unexpected decl");
907 bool RetainSummaryManager::applyParamAnnotationEffect(
912 hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,
913 GeneralizedConsumedAttr>(pd, QT)) {
916 }
else if (
auto K = hasAnyEnabledAttrOf<
917 CFReturnsRetainedAttr, OSReturnsRetainedAttr,
918 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,
919 GeneralizedReturnsRetainedAttr>(pd, QT)) {
926 bool HasRetainedOnZero = pd->
hasAttr<OSReturnsRetainedOnZeroAttr>();
927 bool HasRetainedOnNonZero = pd->
hasAttr<OSReturnsRetainedOnNonZeroAttr>();
938 if (ShouldSplit && SuccessOnZero) {
940 }
else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {
951 }
else if (
auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,
952 OSReturnsNotRetainedAttr,
953 GeneralizedReturnsNotRetainedAttr>(
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))
971 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
976 assert(Summ &&
"Must have a summary to add annotations to.");
980 unsigned parm_idx = 0;
982 pe = FD->
param_end(); pi != pe; ++pi, ++parm_idx)
983 applyParamAnnotationEffect(*pi, parm_idx, FD, Template);
989 if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy))
994 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
999 assert(Summ &&
"Must have a valid summary to add annotations to");
1003 if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->
getReturnType()))
1007 unsigned parm_idx = 0;
1010 applyParamAnnotationEffect(*pi, parm_idx, MD, Template);
1018 RetainSummaryManager::getStandardMethodSummary(
const ObjCMethodDecl *MD,
1040 switch (S.getMethodFamily()) {
1057 ResultEff = ObjCInitRetE;
1065 ResultEff = ObjCAllocRetE;
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)
1108 return getDefaultSummary();
1110 return getPersistentSummary(ResultEff,
ArgEffects(AF.getEmptyMap()),
1115 RetainSummaryManager::getClassMethodSummary(
const ObjCMessageExpr *ME) {
1120 ME->
getType(), ObjCClassMethodSummaries);
1123 const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
1130 if (!ReceiverType.
isNull())
1132 ReceiverClass = PT->getInterfaceDecl();
1144 if (!Method && ReceiverClass)
1147 return getMethodSummary(S, ReceiverClass, Method, ME->
getType(),
1148 ObjCMethodSummaries);
1152 RetainSummaryManager::getMethodSummary(
Selector S,
1155 ObjCMethodSummariesTy &CachedSummaries) {
1158 if (!TrackObjCAndCFObjects)
1159 return getDefaultSummary();
1165 Summ = getStandardMethodSummary(MD, S, RetTy);
1168 updateSummaryFromAnnotations(Summ, MD);
1177 void RetainSummaryManager::InitializeClassMethodSummaries() {
1181 addClassMethSummary(
"NSAssertionHandler",
"currentHandler",
1187 addClassMethSummary(
"NSAutoreleasePool",
"addObject",
1193 void RetainSummaryManager::InitializeMethodSummaries() {
1208 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,
1220 Summ = getPersistentSummary(
NoRet, ScratchArgs,
1244 addClassMethSummary(
"NSWindow",
"alloc", NoTrackYet);
1250 addClassMethSummary(
"NSPanel",
"alloc", NoTrackYet);
1255 addClassMethSummary(
"NSNull",
"null", NoTrackYet);
1259 addClassMethSummary(
"NSAutoreleasePool",
"alloc", NoTrackYet);
1260 addClassMethSummary(
"NSAutoreleasePool",
"allocWithZone", NoTrackYet,
false);
1261 addClassMethSummary(
"NSAutoreleasePool",
"new", NoTrackYet);
1264 addInstMethSummary(
"QCRenderer", AllocSumm,
"createSnapshotImageOfType");
1265 addInstMethSummary(
"QCView", AllocSumm,
"createSnapshotImageOfType");
1270 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect");
1271 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect",
1272 "format",
"colorSpace");
1273 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGLayerWithSize",
"info");
1277 RetainSummaryManager::getMethodSummary(
const ObjCMethodDecl *MD) {
1282 ObjCMethodSummariesTy *CachedSummaries;
1284 CachedSummaries = &ObjCMethodSummaries;
1286 CachedSummaries = &ObjCClassMethodSummaries;
1288 return getMethodSummary(S,
ID, MD, ResultTy, *CachedSummaries);