clang: lib/Analysis/RetainSummaryManager.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

21#include

22

23using namespace clang;

24using namespace ento;

25

26template

30

31

32

33template <class T, class P, class... ToCompare>

35 return std::is_same_v<T, P> || isOneOf<T, ToCompare...>();

36}

37

38namespace {

39

40

41struct GeneralizedReturnsRetainedAttr {

42 static bool classof(const Attr *A) {

43 if (auto AA = dyn_cast(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(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(A))

60 return AA->getAnnotation() == "rc_ownership_consumed";

61 return false;

62 }

63};

64

65}

66

67template

68std::optional RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,

71 if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,

72 CFReturnsNotRetainedAttr>()) {

73 if (!TrackObjCAndCFObjects)

74 return std::nullopt;

75

77 } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,

78 NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,

79 NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {

80

81 if (!TrackObjCAndCFObjects)

82 return std::nullopt;

83

84 if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,

85 NSReturnsNotRetainedAttr>() &&

87 return std::nullopt;

89 } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,

90 OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,

91 OSReturnsRetainedOnZeroAttr,

92 OSReturnsRetainedOnNonZeroAttr>()) {

93 if (!TrackOSObjects)

94 return std::nullopt;

96 } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,

97 GeneralizedReturnsRetainedAttr,

98 GeneralizedConsumedAttr>()) {

100 } else {

101 llvm_unreachable("Unexpected attribute");

102 }

104 return K;

105 return std::nullopt;

106}

107

108template <class T1, class T2, class... Others>

109std::optional RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,

110 QualType QT) {

111 if (auto Out = hasAnyEnabledAttrOf(D, QT))

112 return Out;

113 return hasAnyEnabledAttrOf<T2, Others...>(D, QT);

114}

115

117RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {

118

120 ::llvm::FoldingSetNodeID ID;

122

123 void *Pos;

124 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);

125

126 if (!N) {

127 N = (CachedSummaryNode *) BPAlloc.Allocate();

128 new (N) CachedSummaryNode(OldSumm);

129 SimpleSummaries.InsertNode(N, Pos);

130 }

131

132 return &N->getValue();

133 }

134

135 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate();

136 new (Summ) RetainSummary(OldSumm);

137 return Summ;

138}

139

141 StringRef ClassName) {

144 cxxRecordDecl(isSameOrDerivedFrom(std::string(ClassName)));

146}

147

153

155 return D && isSubclass(D, "OSMetaClassBase") &&

157}

158

160

162 return S == "requiredMetaCast";

163}

164

166 return S == "metaCast";

167}

168

169

173

175 return StringRef(Ty.getAsString()).starts_with("isl_");

176}

177

181

183 for (const auto *Ann : D->specific_attrs()) {

184 if (Ann->getAnnotation() == rcAnnotation)

185 return true;

186 }

187 return false;

188}

189

191 return FName.starts_with_insensitive("retain") ||

192 FName.ends_with_insensitive("retain");

193}

194

196 return FName.starts_with_insensitive("release") ||

197 FName.ends_with_insensitive("release");

198}

199

201 return FName.starts_with_insensitive("autorelease") ||

202 FName.ends_with_insensitive("autorelease");

203}

204

206 return FName.contains_insensitive("MakeCollectable");

207}

208

209

210

213 return true;

214

220 return true;

221 }

222

223 return false;

224}

225

226bool

230 if (!RD)

231 return false;

233 if (II && II->getName() == "smart_ptr")

234 if (const auto *ND = dyn_cast(RD->getDeclContext()))

235 if (ND->getNameAsString() == "os")

236 return true;

237 return false;

238}

239

241RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,

242 StringRef FName, QualType RetTy) {

243 assert(TrackOSObjects &&

244 "Requesting a summary for an OSObject but OSObjects are not tracked");

245

251 return getDefaultSummary();

252

253

254

255

256 if (FName.ends_with("Matching")) {

257 return getPersistentStopSummary();

258 }

259

260

261

262 if ((!FName.starts_with("get") && !FName.starts_with("Get")) ||

264 return getOSSummaryCreateRule(FD);

265 } else {

266 return getOSSummaryGetRule(FD);

267 }

268 }

269 }

270

271 if (const auto *MD = dyn_cast(FD)) {

272 const CXXRecordDecl *Parent = MD->getParent();

274 if (FName == "release" || FName == "taggedRelease")

275 return getOSSummaryReleaseRule(FD);

276

277 if (FName == "retain" || FName == "taggedRetain")

278 return getOSSummaryRetainRule(FD);

279

280 if (FName == "free")

281 return getOSSummaryFreeRule(FD);

282

283 if (MD->getOverloadedOperator() == OO_New)

284 return getOSSummaryCreateRule(MD);

285 }

286 }

287

288 return nullptr;

289}

290

291const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(

292 const FunctionDecl *FD,

293 StringRef FName,

294 QualType RetTy,

295 const FunctionType *FT,

296 bool &AllowAnnotations) {

297

298 ArgEffects ScratchArgs(AF.getEmptyMap());

299

300 std::string RetTyName = RetTy.getAsString();

301 if (FName == "pthread_create" || FName == "pthread_setspecific") {

302

303

304

305 return getPersistentStopSummary();

306 } else if(FName == "NSMakeCollectable") {

307

308 AllowAnnotations = false;

310 : getPersistentStopSummary();

311 } else if (FName == "CMBufferQueueDequeueAndRetain" ||

312 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {

313

314

316 ScratchArgs,

319 } else if (FName == "CFPlugInInstanceCreate") {

321 } else if (FName == "IORegistryEntrySearchCFProperty" ||

322 (RetTyName == "CFMutableDictionaryRef" &&

323 (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||

324 FName == "IOServiceNameMatching" ||

325 FName == "IORegistryEntryIDMatching" ||

326 FName == "IOOpenFirmwarePathMatching"))) {

327

328

331 } else if (FName == "IOServiceGetMatchingService" ||

332 FName == "IOServiceGetMatchingServices") {

333

334

335 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));

337 ScratchArgs,

339 } else if (FName == "IOServiceAddNotification" ||

340 FName == "IOServiceAddMatchingNotification") {

341

342

343 ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));

345 ScratchArgs,

347 } else if (FName == "CVPixelBufferCreateWithBytes") {

348

349

350

351

352

353

354 ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));

356 ScratchArgs,

358 } else if (FName == "CGBitmapContextCreateWithData") {

359

360

361

362

363 ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));

366 } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {

367

368 ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));

370 ScratchArgs,

372 } else if (FName == "VTCompressionSessionEncodeFrame" ||

373 FName == "VTCompressionSessionEncodeMultiImageFrame") {

374

375

376

377

378

379 ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));

381 ScratchArgs,

383 } else if (FName == "dispatch_set_context" ||

384 FName == "xpc_connection_set_context") {

385

386

387

388

389 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));

391 ScratchArgs,

393 } else if (FName.starts_with("NSLog")) {

394 return getDoNothingSummary();

395 } else if (FName.starts_with("NS") && FName.contains("Insert")) {

396

397

398 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));

399 ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));

401 ScratchArgs, ArgEffect(DoNothing),

403 }

404

406

407

410

411

412

413

414 AllowAnnotations = false;

415

416 return getUnarySummary(FT, IncRef);

418

419

420 AllowAnnotations = false;

421

424 AllowAnnotations = false;

425 return getUnarySummary(FT, DoNothing);

426 } else {

427 return getCFCreateGetRuleSummary(FD);

428 }

429 }

430

431

435 return getUnarySummary(FT, IncRef);

436 else

437 return getCFCreateGetRuleSummary(FD);

438 }

439

440

441

442

444 return getCFCreateGetRuleSummary(FD);

445 }

446

447 if (FD->hasAttr()) {

448 return getCFCreateGetRuleSummary(FD);

449 }

450 }

451

452

453

454 if (FName.starts_with("CG") || FName.starts_with("CF")) {

455

456 FName = FName.substr(FName.starts_with("CGCF") ? 4 : 2);

457

459 return getUnarySummary(FT, DecRef);

460 else {

461 assert(ScratchArgs.isEmpty());

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

478 (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||

479 StrInStrNoCase(FName, "AddValue") != StringRef::npos ||

480 StrInStrNoCase(FName, "SetValue") != StringRef::npos ||

481 StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||

482 StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)

485

488 }

489 }

490

491 return nullptr;

492}

493

495RetainSummaryManager::generateSummary(const FunctionDecl *FD,

496 bool &AllowAnnotations) {

497

499 return getPersistentStopSummary();

500

502

503 StringRef FName = II ? II->getName() : "";

504

505

506

507 FName = FName.substr(FName.find_first_not_of('_'));

508

509

510 const auto *FT = FD->getType()->castAs();

512

513 if (TrackOSObjects)

514 if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))

515 return S;

516

517 if (const auto *MD = dyn_cast(FD))

524

525 if (TrackObjCAndCFObjects)

526 if (const RetainSummary *S =

527 getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))

528 return S;

529

530 return getDefaultSummary();

531}

532

534RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {

535

536 if (!FD)

537 return getDefaultSummary();

538

539

540 FuncSummariesTy::iterator I = FuncSummaries.find(FD);

541 if (I != FuncSummaries.end())

542 return I->second;

543

544

545 bool AllowAnnotations = true;

546 const RetainSummary *S = generateSummary(FD, AllowAnnotations);

547

548

549 if (AllowAnnotations)

550 updateSummaryFromAnnotations(S, FD);

551

552 FuncSummaries[FD] = S;

553 return S;

554}

555

556

557

558

559

579 }

580

581 llvm_unreachable("Unknown ArgEffect kind");

582}

583

585RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S,

586 AnyCall &C) {

589

590 ArgEffects ScratchArgs(AF.getEmptyMap());

592 for (ArgEffects::iterator I = CustomArgEffects.begin(),

593 E = CustomArgEffects.end();

594 I != E; ++I) {

597 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);

598 }

599

601

602

603

604

605 if (const IdentifierInfo *Name = C.getIdentifier()) {

606

607

608

609

610 if (Name->isStr("CGBitmapContextCreateWithData") ||

611 Name->isStr("dispatch_data_create"))

613 }

614

615 return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);

616}

617

618void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(

620

622

625}

626

627

628void RetainSummaryManager::updateSummaryForArgumentTypes(

631

632 unsigned parm_idx = 0;

633 for (auto pi = C.param_begin(), pe = C.param_end(); pi != pe;

634 ++pi, ++parm_idx) {

635 QualType QT = (*pi)->getType();

636

637

639 continue;

640

642

651 }

652

654 Template->addArg(AF, parm_idx,

655 ArgEffect(RS->getDefaultArgEffect().getKind(), K));

656 }

657}

658

661 bool HasNonZeroCallbackArg,

662 bool IsReceiverUnconsumedSelf,

665 switch (C.getKind()) {

671 Summ = getFunctionSummary(cast_or_null(C.getDecl()));

672 break;

675

676 return getPersistentStopSummary();

678 const auto *ME = cast_or_null(C.getExpr());

679 if (!ME) {

681 } else if (ME->isInstanceMessage()) {

682 Summ = getInstanceMethodSummary(ME, ReceiverType);

683 } else {

684 Summ = getClassMethodSummary(ME);

685 }

686 break;

687 }

688 }

689

690 if (HasNonZeroCallbackArg)

691 Summ = updateSummaryForNonZeroCallbackArg(Summ, C);

692

693 if (IsReceiverUnconsumedSelf)

694 updateSummaryForReceiverUnconsumedSelf(Summ);

695

696 updateSummaryForArgumentTypes(C, Summ);

697

698 assert(Summ && "Unknown call type?");

699 return Summ;

700}

701

702

704RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {

706 return getCFSummaryCreateRule(FD);

707

708 return getCFSummaryGetRule(FD);

709}

710

712 const Decl *FD) {

713 return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");

714}

715

716std::optionalRetainSummaryManager::BehaviorSummary

718 bool &hasTrustedImplementationAnnotation) {

719

721 if (!II)

722 return std::nullopt;

723

724 StringRef FName = II->getName();

725 FName = FName.substr(FName.find_first_not_of('_'));

726

729 if (II->isStr("NSMakeCollectable"))

732

733

734

735 if (FName == "CMBufferQueueDequeueAndRetain" ||

736 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {

737

738

739 return std::nullopt;

740 }

748

749

750

751

752

753

754 if (TrackOSObjects) {

762 }

763 }

764

767 hasTrustedImplementationAnnotation = true;

769 }

770 }

771

772 if (const auto *MD = dyn_cast(FD)) {

775 if (FName == "release" || FName == "retain")

777 }

778

779 return std::nullopt;

780}

781

783RetainSummaryManager::getUnarySummary(const FunctionType* FT,

785

786

787 ArgEffects ScratchArgs(AF.getEmptyMap());

788

789

790

793 return getPersistentStopSummary();

794

796

797 ScratchArgs = AF.add(ScratchArgs, 0, Effect);

799 ScratchArgs,

801}

802

804RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {

806 AF.getEmptyMap(),

810}

811

813RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {

815 AF.getEmptyMap(),

819}

820

822RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {

824 AF.getEmptyMap(),

825 ArgEffect(DoNothing),

826 ArgEffect(DoNothing),

828}

829

831RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) {

833 AF.getEmptyMap());

834}

835

837RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) {

839 AF.getEmptyMap());

840}

841

843RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {

846}

847

849RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {

853}

854

855

856

857

858

859

860

861

862std::optional

863RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,

864 const Decl *D) {

865 if (hasAnyEnabledAttrOf(D, RetTy))

866 return ObjCAllocRetE;

867

868 if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,

869 GeneralizedReturnsRetainedAttr>(D, RetTy))

871

872 if (auto K = hasAnyEnabledAttrOf<

873 CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,

874 GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,

875 NSReturnsAutoreleasedAttr>(D, RetTy))

877

878 if (const auto *MD = dyn_cast(D))

879 for (const auto *PD : MD->overridden_methods())

880 if (auto RE = getRetEffectFromAnnotations(RetTy, PD))

881 return RE;

882

883 return std::nullopt;

884}

885

886

887

889 StringRef Name) {

891 const auto &Context = T->getDecl()->getASTContext();

892 if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name))

893 return true;

894 QT = T->getDecl()->getUnderlyingType();

895 }

896 return false;

897}

898

900 if (const auto *FD = dyn_cast(ND)) {

902 } else if (const auto *MD = dyn_cast(ND)) {

903 return MD->getReturnType();

904 } else {

905 llvm_unreachable("Unexpected decl");

906 }

907}

908

909bool RetainSummaryManager::applyParamAnnotationEffect(

910 const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD,

912 QualType QT = pd->getType();

913 if (auto K =

914 hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,

915 GeneralizedConsumedAttr>(pd, QT)) {

916 Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K));

917 return true;

918 } else if (auto K = hasAnyEnabledAttrOf<

919 CFReturnsRetainedAttr, OSReturnsRetainedAttr,

920 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,

921 GeneralizedReturnsRetainedAttr>(pd, QT)) {

922

923

924

927

928 bool HasRetainedOnZero = pd->hasAttr();

929 bool HasRetainedOnNonZero = pd->hasAttr();

930

931

932

933

934

935 bool SuccessOnZero =

936 HasRetainedOnZero ||

937 (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero);

940 if (ShouldSplit && SuccessOnZero) {

942 } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {

944 }

946 }

947

948

949

950

951

952 return true;

953 } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,

954 OSReturnsNotRetainedAttr,

955 GeneralizedReturnsNotRetainedAttr>(

956 pd, QT)) {

958 return true;

959 }

960

961 if (const auto *MD = dyn_cast(FD)) {

962 for (const auto *OD : MD->overridden_methods()) {

963 const ParmVarDecl *OP = OD->parameters()[parm_idx];

964 if (applyParamAnnotationEffect(OP, parm_idx, OD, Template))

965 return true;

966 }

967 }

968

969 return false;

970}

971

972void

973RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,

974 const FunctionDecl *FD) {

975 if (!FD)

976 return;

977

978 assert(Summ && "Must have a summary to add annotations to.");

980

981

982 unsigned parm_idx = 0;

984 pe = FD->param_end(); pi != pe; ++pi, ++parm_idx)

985 applyParamAnnotationEffect(*pi, parm_idx, FD, Template);

986

988 if (std::optional RetE = getRetEffectFromAnnotations(RetTy, FD))

989 Template->setRetEffect(*RetE);

990

991 if (hasAnyEnabledAttrOf(FD, RetTy))

993}

994

995void

996RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,

997 const ObjCMethodDecl *MD) {

998 if (!MD)

999 return;

1000

1001 assert(Summ && "Must have a valid summary to add annotations to");

1003

1004

1005 if (hasAnyEnabledAttrOf(MD, MD->getReturnType()))

1007

1008

1009 unsigned parm_idx = 0;

1011 ++pi, ++parm_idx)

1012 applyParamAnnotationEffect(*pi, parm_idx, MD, Template);

1013

1015 if (std::optional RetE = getRetEffectFromAnnotations(RetTy, MD))

1016 Template->setRetEffect(*RetE);

1017}

1018

1020RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,

1021 Selector S, QualType RetTy) {

1022

1025

1026

1031

1032

1033

1037

1038

1039

1040

1041 if (MD) {

1048 break;

1049 default:

1051 break;

1052 }

1053 } else {

1055 }

1056 }

1057 break;

1059 ResultEff = ObjCInitRetE;

1061 break;

1067 ResultEff = ObjCAllocRetE;

1070 break;

1073 break;

1076 break;

1079 break;

1082 break;

1084

1085 break;

1088

1089 break;

1090 }

1091

1092

1093

1094

1095

1097 for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {

1099 if (Slot.ends_with_insensitive("delegate")) {

1100 if (ResultEff == ObjCInitRetE)

1102 else

1104 }

1105 }

1106 }

1107

1110 return getDefaultSummary();

1111

1112 return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),

1113 ArgEffect(ReceiverEff), ArgEffect(MayEscape));

1114}

1115

1117RetainSummaryManager::getClassMethodSummary(const ObjCMessageExpr *ME) {

1120

1122 ME->getType(), ObjCClassMethodSummaries);

1123}

1124

1125const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(

1126 const ObjCMessageExpr *ME,

1127 QualType ReceiverType) {

1128 const ObjCInterfaceDecl *ReceiverClass = nullptr;

1129

1130

1131

1132 if (!ReceiverType.isNull())

1133 if (const auto *PT = ReceiverType->getAs())

1134 ReceiverClass = PT->getInterfaceDecl();

1135

1136

1137 if (!ReceiverClass)

1139

1140

1141

1142

1143

1146 if (Method && ReceiverClass)

1148

1149 return getMethodSummary(S, ReceiverClass, Method, ME->getType(),

1150 ObjCMethodSummaries);

1151}

1152

1154RetainSummaryManager::getMethodSummary(Selector S,

1155 const ObjCInterfaceDecl *ID,

1156 const ObjCMethodDecl *MD, QualType RetTy,

1157 ObjCMethodSummariesTy &CachedSummaries) {

1158

1159

1160 if (!TrackObjCAndCFObjects)

1161 return getDefaultSummary();

1162

1163

1164 const RetainSummary *Summ = CachedSummaries.find(ID, S);

1165

1166 if (!Summ) {

1167 Summ = getStandardMethodSummary(MD, S, RetTy);

1168

1169

1170 updateSummaryFromAnnotations(Summ, MD);

1171

1172

1173 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;

1174 }

1175

1176 return Summ;

1177}

1178

1179void RetainSummaryManager::InitializeClassMethodSummaries() {

1180 ArgEffects ScratchArgs = AF.getEmptyMap();

1181

1182

1183 addClassMethSummary("NSAssertionHandler", "currentHandler",

1185 ScratchArgs));

1186

1187

1188 ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));

1189 addClassMethSummary("NSAutoreleasePool", "addObject",

1193}

1194

1195void RetainSummaryManager::InitializeMethodSummaries() {

1196

1197 ArgEffects ScratchArgs = AF.getEmptyMap();

1198

1199

1200 const RetainSummary *InitSumm = getPersistentSummary(

1203

1204

1205

1206 addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),

1207 InitSumm);

1208

1209

1210 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,

1211 ScratchArgs);

1212 const RetainSummary *CFAllocSumm =

1214

1215

1217 const RetainSummary *Summ = getPersistentSummary(

1220

1221

1222 Summ = getPersistentSummary(NoRet, ScratchArgs,

1225

1226

1227 Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc,

1230

1231

1232 Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease,

1234 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);

1235

1236

1237

1238

1239

1240 const RetainSummary *NoTrackYet =

1243

1244 addClassMethSummary("NSWindow", "alloc", NoTrackYet);

1245

1246

1247

1248

1249

1250 addClassMethSummary("NSPanel", "alloc", NoTrackYet);

1251

1252

1253

1254 addClassMethSummary("NSNull", "null", NoTrackYet);

1255

1256

1257

1258 addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);

1259 addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);

1260 addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);

1261

1262

1263 addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");

1264 addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");

1265

1266

1267

1268

1269 addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");

1270 addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",

1271 "format", "colorSpace");

1272 addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");

1273}

1274

1276RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {

1280

1281 ObjCMethodSummariesTy *CachedSummaries;

1283 CachedSummaries = &ObjCMethodSummaries;

1284 else

1285 CachedSummaries = &ObjCClassMethodSummaries;

1286

1287 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);

1288}

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

static bool isSubclass(const ObjCInterfaceDecl *Class, const IdentifierInfo *II)

static bool isOSObjectRelated(const CXXMethodDecl *MD)

A function is OSObject related if it is declared on a subclass of OSObject, or any of the parameters ...

Definition RetainSummaryManager.cpp:211

static bool isISLObjectRef(QualType Ty)

Definition RetainSummaryManager.cpp:174

static bool isRelease(const FunctionDecl *FD, StringRef FName)

Definition RetainSummaryManager.cpp:195

static bool hasTypedefNamed(QualType QT, StringRef Name)

Definition RetainSummaryManager.cpp:888

static bool isOSObjectRequiredCast(StringRef S)

Definition RetainSummaryManager.cpp:161

static ArgEffect getStopTrackingHardEquivalent(ArgEffect E)

Definition RetainSummaryManager.cpp:560

static constexpr bool isOneOf()

Definition RetainSummaryManager.cpp:27

static bool isOSIteratorSubclass(const Decl *D)

Definition RetainSummaryManager.cpp:178

static QualType getCallableReturnType(const NamedDecl *ND)

Definition RetainSummaryManager.cpp:899

static bool isAutorelease(const FunctionDecl *FD, StringRef FName)

Definition RetainSummaryManager.cpp:200

static bool isExactClass(const Decl *D, StringRef ClassName)

Definition RetainSummaryManager.cpp:148

static bool isOSObjectPtr(QualType QT)

Definition RetainSummaryManager.cpp:170

static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation)

Definition RetainSummaryManager.cpp:182

static bool isOSObjectSubclass(const Decl *D)

Definition RetainSummaryManager.cpp:154

static bool isOSObjectThisCast(StringRef S)

Definition RetainSummaryManager.cpp:165

static bool isMakeCollectable(StringRef FName)

Definition RetainSummaryManager.cpp:205

static bool isOSObjectDynamicCast(StringRef S)

Definition RetainSummaryManager.cpp:159

static bool isRetain(const FunctionDecl *FD, StringRef FName)

Definition RetainSummaryManager.cpp:190

An instance of this class corresponds to a call.

@ Destructor

An implicit C++ destructor call (called implicitly or by operator 'delete')

@ ObjCMethod

A call to an Objective-C method.

@ Deallocator

A C++ deallocation function call (operator delete), via C++ delete-expression.

@ Function

A function, function pointer, or a C++ method call.

@ Allocator

A C++ allocation function call (operator new), via C++ new-expression.

@ Constructor

An implicit or explicit C++ constructor call.

@ InheritedConstructor

A C++ inherited constructor produced by a "using T::T" directive.

@ Block

A call to an Objective-C block.

Represents a static or instance method of a struct/union/class.

const CXXRecordDecl * getParent() const

Return the parent of this method declaration, which is the class in which this method is defined.

Represents a C++ struct/union/class.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

unsigned getNumArgs() const

getNumArgs - Return the number of actual arguments to this call.

QualType getCallReturnType(const ASTContext &Ctx) const

getCallReturnType - Get the return type of the call expr.

DeclContext * getParent()

getParent - Returns the containing DeclContext.

Decl - This represents one declaration (or definition), e.g.

ASTContext & getASTContext() const LLVM_READONLY

bool isImplicit() const

isImplicit - Indicates whether the declaration was implicitly generated by the implementation.

llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const

Represents a function declaration or definition.

param_iterator param_end()

QualType getReturnType() const

ArrayRef< ParmVarDecl * > parameters() const

param_iterator param_begin()

FunctionDecl * getDefinition()

Get the definition for this declaration.

size_t param_size() const

Represents a prototype with parameter type info, e.g.

unsigned getNumParams() const

FunctionType - C99 6.7.5.3 - Function Declarators.

QualType getReturnType() const

One of these records is kept for each identifier that is lexed.

bool isStr(const char(&Str)[StrLen]) const

Return true if this is the identifier for the specified string.

StringRef getName() const

Return the actual identifier string.

This represents a decl that may have a name.

IdentifierInfo * getIdentifier() const

Get the identifier that names this declaration, if there is one.

ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const

Selector getSelector() const

bool isInstanceMessage() const

Determine whether this is an instance message to either a computed object or to super.

ObjCInterfaceDecl * getReceiverInterface() const

Retrieve the Objective-C interface to which this message is being directed, if known.

const ObjCMethodDecl * getMethodDecl() const

param_const_iterator param_end() const

param_const_iterator param_begin() const

Selector getSelector() const

bool isInstanceMethod() const

ObjCMethodFamily getMethodFamily() const

Determines the family of this method.

QualType getReturnType() const

ObjCInterfaceDecl * getClassInterface()

Represents a parameter to a function.

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getCanonicalType() const

static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)

StringRef getNameForSlot(unsigned argIndex) const

Retrieve the name at a given position in the selector.

bool isKeywordSelector() const

ObjCMethodFamily getMethodFamily() const

Derive the conventional family of this method.

unsigned getNumArgs() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isPointerType() const

const T * castAs() const

Member-template castAs.

const CXXRecordDecl * getPointeeCXXRecordDecl() const

If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isObjCIdType() const

const T * getAs() const

Member-template getAs'.

An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method.

ArgEffect withKind(ArgEffectKind NewK)

ArgEffectKind getKind() const

static RetEffect MakeNotOwned(ObjKind o)

static RetEffect MakeOwned(ObjKind o)

@ NoRet

Indicates that no retain count information is tracked for the return value.

static RetEffect MakeNoRet()

static RetEffect MakeNoRetHard()

bool isTrustedReferenceCountImplementation(const Decl *FD)

Definition RetainSummaryManager.cpp:711

std::optional< BehaviorSummary > canEval(const CallExpr *CE, const FunctionDecl *FD, bool &hasTrustedImplementationAnnotation)

Definition RetainSummaryManager.cpp:717

static bool isKnownSmartPointer(QualType QT)

Definition RetainSummaryManager.cpp:227

const RetainSummary * getSummary(AnyCall C, bool HasNonZeroCallbackArg=false, bool IsReceiverUnconsumedSelf=false, QualType ReceiverType={})

Definition RetainSummaryManager.cpp:660

friend class RetainSummaryTemplate

Summary for a function with respect to ownership changes.

ArgEffect getReceiverEffect() const

getReceiverEffect - Returns the effect on the receiver of the call.

RetEffect getRetEffect() const

getRetEffect - Returns the effect on the return value of the call.

bool isSimple() const

A retain summary is simple if it has no ArgEffects other than the default.

ArgEffects getArgEffects() const

void Profile(llvm::FoldingSetNodeID &ID) const

Profile this summary for inclusion in a FoldingSet.

internal::Matcher< Decl > DeclarationMatcher

Types of matchers for the top-level classes in the AST class hierarchy.

internal::Matcher< NamedDecl > hasName(StringRef Name)

Matches NamedDecl nodes that have the specified name.

SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)

Returns the results of matching Matcher on Node.

const internal::VariadicDynCastAllOfMatcher< Decl, CXXRecordDecl > cxxRecordDecl

Matches C++ class declarations.

bool isCocoaObjectRef(QualType T)

bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())

bool followsCreateRule(const FunctionDecl *FD)

bool isCFObjectRef(QualType T)

llvm::ImmutableMap< unsigned, ArgEffect > ArgEffects

ArgEffects summarizes the effects of a function/method call on all of its arguments.

ObjKind

Determines the object kind of a tracked object.

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

@ Generalized

Indicates that the tracked object is a generalized object.

@ CF

Indicates that the tracked object is a CF object.

@ AnyObj

Indicates that the tracked object could be a CF or Objective-C object.

@ ObjC

Indicates that the tracked object is an Objective-C object.

@ IncRef

The argument has its reference count increased by 1.

@ UnretainedOutParameter

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +0 v...

@ DoNothing

There is no effect.

@ RetainedOutParameter

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ RetainedOutParameterOnZero

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ MayEscape

The argument is treated as potentially escaping, meaning that even when its reference count hits 0 it...

@ StopTracking

All typestate tracking of the object ceases.

@ Dealloc

The argument is treated as if the referenced object was deallocated.

@ Autorelease

The argument is treated as if an -autorelease message had been sent to the referenced object.

@ RetainedOutParameterOnNonZero

The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...

@ DecRef

The argument has its reference count decreased by 1.

@ StopTrackingHard

All typestate tracking of the object ceases.

@ DecRefAndStopTrackingHard

Performs the combined functionality of DecRef and StopTrackingHard.

@ DecRefBridgedTransferred

The argument has its reference count decreased by 1 to model a transferred bridge cast under ARC.

bool NoRet(InterpState &S, CodePtr OpPC)

The JSON file list parser is used to communicate input to InstallAPI.

bool isa(CodeGen::Address addr)

@ OMF_None

No particular method family.

static bool classof(const Stmt *T)

Selector GetUnarySelector(StringRef name, ASTContext &Ctx)

Utility function for constructing an unary selector.

const FunctionProtoType * T

@ Template

We are parsing a template declaration.

Selector GetNullarySelector(StringRef name, ASTContext &Ctx)

Utility function for constructing a nullary selector.

U cast(CodeGen::Address addr)

@ Class

The "class" keyword introduces the elaborated-type-specifier.