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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

22#include

23

24using namespace clang;

25using namespace ento;

26

27template

29 return false;

30}

31

32

33

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

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

37}

38

39namespace {

40

41

42struct GeneralizedReturnsRetainedAttr {

43 static bool classof(const Attr *A) {

44 if (auto AA = dyn_cast(A))

45 return AA->getAnnotation() == "rc_ownership_returns_retained";

46 return false;

47 }

48};

49

50struct GeneralizedReturnsNotRetainedAttr {

51 static bool classof(const Attr *A) {

52 if (auto AA = dyn_cast(A))

53 return AA->getAnnotation() == "rc_ownership_returns_not_retained";

54 return false;

55 }

56};

57

58struct GeneralizedConsumedAttr {

59 static bool classof(const Attr *A) {

60 if (auto AA = dyn_cast(A))

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

62 return false;

63 }

64};

65

66}

67

68template

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

72 if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,

73 CFReturnsNotRetainedAttr>()) {

74 if (!TrackObjCAndCFObjects)

75 return std::nullopt;

76

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

79 NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,

80 NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {

81

82 if (!TrackObjCAndCFObjects)

83 return std::nullopt;

84

85 if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,

86 NSReturnsNotRetainedAttr>() &&

88 return std::nullopt;

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

91 OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,

92 OSReturnsRetainedOnZeroAttr,

93 OSReturnsRetainedOnNonZeroAttr>()) {

94 if (!TrackOSObjects)

95 return std::nullopt;

97 } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,

98 GeneralizedReturnsRetainedAttr,

99 GeneralizedConsumedAttr>()) {

101 } else {

102 llvm_unreachable("Unexpected attribute");

103 }

105 return K;

106 return std::nullopt;

107}

108

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

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

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

113 return Out;

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

115}

116

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

119

121 ::llvm::FoldingSetNodeID ID;

123

124 void *Pos;

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

126

127 if (!N) {

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

129 new (N) CachedSummaryNode(OldSumm);

130 SimpleSummaries.InsertNode(N, Pos);

131 }

132

133 return &N->getValue();

134 }

135

138 return Summ;

139}

140

142 StringRef ClassName) {

143 using namespace ast_matchers;

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

147}

148

150 using namespace ast_matchers;

154}

155

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

159}

160

162

164 return S == "requiredMetaCast";

165}

166

168 return S == "metaCast";

169}

170

171

174}

175

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

178}

179

182}

183

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

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

187 return true;

188 }

189 return false;

190}

191

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

194 FName.ends_with_insensitive("retain");

195}

196

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

199 FName.ends_with_insensitive("release");

200}

201

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

204 FName.ends_with_insensitive("autorelease");

205}

206

208 return FName.contains_insensitive("MakeCollectable");

209}

210

211

212

215 return true;

216

222 return true;

223 }

224

225 return false;

226}

227

228bool

232 if (!RD)

233 return false;

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

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

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

238 return true;

239 return false;

240}

241

243RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,

244 StringRef FName, QualType RetTy) {

245 assert(TrackOSObjects &&

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

247

253 return getDefaultSummary();

254

255

256

257

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

259 return getPersistentStopSummary();

260 }

261

262

263

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

266 return getOSSummaryCreateRule(FD);

267 } else {

268 return getOSSummaryGetRule(FD);

269 }

270 }

271 }

272

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

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

277 return getOSSummaryReleaseRule(FD);

278

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

280 return getOSSummaryRetainRule(FD);

281

282 if (FName == "free")

283 return getOSSummaryFreeRule(FD);

284

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

286 return getOSSummaryCreateRule(MD);

287 }

288 }

289

290 return nullptr;

291}

292

293const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(

295 StringRef FName,

298 bool &AllowAnnotations) {

299

300 ArgEffects ScratchArgs(AF.getEmptyMap());

301

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

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

304

305

306

307 return getPersistentStopSummary();

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

309

310 AllowAnnotations = false;

312 : getPersistentStopSummary();

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

314 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {

315

316

318 ScratchArgs,

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

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

324 (RetTyName == "CFMutableDictionaryRef" &&

325 (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||

326 FName == "IOServiceNameMatching" ||

327 FName == "IORegistryEntryIDMatching" ||

328 FName == "IOOpenFirmwarePathMatching"))) {

329

330

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

334 FName == "IOServiceGetMatchingServices") {

335

336

339 ScratchArgs,

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

342 FName == "IOServiceAddMatchingNotification") {

343

344

347 ScratchArgs,

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

350

351

352

353

354

355

358 ScratchArgs,

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

361

362

363

364

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

369

372 ScratchArgs,

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

375 FName == "VTCompressionSessionEncodeMultiImageFrame") {

376

377

378

379

380

383 ScratchArgs,

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

386 FName == "xpc_connection_set_context") {

387

388

389

390

393 ScratchArgs,

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

396 return getDoNothingSummary();

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

398

399

405 }

406

408

409

412

413

414

415

416 AllowAnnotations = false;

417

418 return getUnarySummary(FT, IncRef);

420

421

422 AllowAnnotations = false;

423

426 AllowAnnotations = false;

427 return getUnarySummary(FT, DoNothing);

428 } else {

429 return getCFCreateGetRuleSummary(FD);

430 }

431 }

432

433

437 return getUnarySummary(FT, IncRef);

438 else

439 return getCFCreateGetRuleSummary(FD);

440 }

441

442

443

444

446 return getCFCreateGetRuleSummary(FD);

447 }

448

449 if (FD->hasAttr()) {

450 return getCFCreateGetRuleSummary(FD);

451 }

452 }

453

454

455

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

457

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

459

461 return getUnarySummary(FT, DecRef);

462 else {

463 assert(ScratchArgs.isEmpty());

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

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

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

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

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

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

487

490 }

491 }

492

493 return nullptr;

494}

495

497RetainSummaryManager::generateSummary(const FunctionDecl *FD,

498 bool &AllowAnnotations) {

499

501 return getPersistentStopSummary();

502

504

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

506

507

508

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

510

511

514

515 if (TrackOSObjects)

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

517 return S;

518

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

526

527 if (TrackObjCAndCFObjects)

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

530 return S;

531

532 return getDefaultSummary();

533}

534

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

537

538 if (!FD)

539 return getDefaultSummary();

540

541

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

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

544 return I->second;

545

546

547 bool AllowAnnotations = true;

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

549

550

551 if (AllowAnnotations)

552 updateSummaryFromAnnotations(S, FD);

553

554 FuncSummaries[FD] = S;

555 return S;

556}

557

558

559

560

561

563 switch (E.getKind()) {

581 }

582

583 llvm_unreachable("Unknown ArgEffect kind");

584}

585

587RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S,

591

592 ArgEffects ScratchArgs(AF.getEmptyMap());

593 ArgEffects CustomArgEffects = S->getArgEffects();

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

595 E = CustomArgEffects.end();

596 I != E; ++I) {

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

600 }

601

603

604

605

606

608

609

610

611

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

613 Name->isStr("dispatch_data_create"))

614 RE = S->getRetEffect();

615 }

616

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

618}

619

620void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(

622

624

627}

628

629

630void RetainSummaryManager::updateSummaryForArgumentTypes(

633

634 unsigned parm_idx = 0;

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

636 ++pi, ++parm_idx) {

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

638

639

641 continue;

642

644

653 }

654

656 Template->addArg(AF, parm_idx,

658 }

659}

660

663 bool HasNonZeroCallbackArg,

664 bool IsReceiverUnconsumedSelf,

667 switch (C.getKind()) {

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

674 break;

677

678 return getPersistentStopSummary();

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

681 if (!ME) {

682 Summ = getMethodSummary(cast(C.getDecl()));

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

684 Summ = getInstanceMethodSummary(ME, ReceiverType);

685 } else {

686 Summ = getClassMethodSummary(ME);

687 }

688 break;

689 }

690 }

691

692 if (HasNonZeroCallbackArg)

693 Summ = updateSummaryForNonZeroCallbackArg(Summ, C);

694

695 if (IsReceiverUnconsumedSelf)

696 updateSummaryForReceiverUnconsumedSelf(Summ);

697

698 updateSummaryForArgumentTypes(C, Summ);

699

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

701 return Summ;

702}

703

704

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

708 return getCFSummaryCreateRule(FD);

709

710 return getCFSummaryGetRule(FD);

711}

712

714 const Decl *FD) {

715 return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");

716}

717

718std::optionalRetainSummaryManager::BehaviorSummary

720 bool &hasTrustedImplementationAnnotation) {

721

723 if (!II)

724 return std::nullopt;

725

726 StringRef FName = II->getName();

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

728

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

734

735

736

737 if (FName == "CMBufferQueueDequeueAndRetain" ||

738 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {

739

740

741 return std::nullopt;

742 }

750

751

752

753

754

755

756 if (TrackOSObjects) {

762 !cast(FD)->isStatic()) {

764 }

765 }

766

769 hasTrustedImplementationAnnotation = true;

771 }

772 }

773

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

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

779 }

780

781 return std::nullopt;

782}

783

785RetainSummaryManager::getUnarySummary(const FunctionType* FT,

787

788

789 ArgEffects ScratchArgs(AF.getEmptyMap());

790

791

792

795 return getPersistentStopSummary();

796

798

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

801 ScratchArgs,

803}

804

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

808 AF.getEmptyMap(),

812}

813

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

817 AF.getEmptyMap(),

821}

822

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

826 AF.getEmptyMap(),

830}

831

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

835 AF.getEmptyMap());

836}

837

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

841 AF.getEmptyMap());

842}

843

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

848}

849

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

855}

856

857

858

859

860

861

862

863

864std::optional

865RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,

867 if (hasAnyEnabledAttrOf(D, RetTy))

868 return ObjCAllocRetE;

869

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

871 GeneralizedReturnsRetainedAttr>(D, RetTy))

873

874 if (auto K = hasAnyEnabledAttrOf<

875 CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,

876 GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,

877 NSReturnsAutoreleasedAttr>(D, RetTy))

879

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

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

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

883 return RE;

884

885 return std::nullopt;

886}

887

888

889

891 StringRef Name) {

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

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

895 return true;

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

897 }

898 return false;

899}

900

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

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

905 return MD->getReturnType();

906 } else {

907 llvm_unreachable("Unexpected decl");

908 }

909}

910

911bool RetainSummaryManager::applyParamAnnotationEffect(

915 if (auto K =

916 hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,

917 GeneralizedConsumedAttr>(pd, QT)) {

919 return true;

920 } else if (auto K = hasAnyEnabledAttrOf<

921 CFReturnsRetainedAttr, OSReturnsRetainedAttr,

922 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,

923 GeneralizedReturnsRetainedAttr>(pd, QT)) {

924

925

926

929

930 bool HasRetainedOnZero = pd->hasAttr();

931 bool HasRetainedOnNonZero = pd->hasAttr();

932

933

934

935

936

937 bool SuccessOnZero =

938 HasRetainedOnZero ||

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

942 if (ShouldSplit && SuccessOnZero) {

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

946 }

948 }

949

950

951

952

953

954 return true;

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

956 OSReturnsNotRetainedAttr,

957 GeneralizedReturnsNotRetainedAttr>(

958 pd, QT)) {

960 return true;

961 }

962

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

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

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

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

967 return true;

968 }

969 }

970

971 return false;

972}

973

974void

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

977 if (!FD)

978 return;

979

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

982

983

984 unsigned parm_idx = 0;

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

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

988

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

992

993 if (hasAnyEnabledAttrOf(FD, RetTy))

995}

996

997void

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

1000 if (!MD)

1001 return;

1002

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

1005

1006

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

1009

1010

1011 unsigned parm_idx = 0;

1013 ++pi, ++parm_idx)

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

1015

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

1019}

1020

1022RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,

1024

1027

1028

1029 switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {

1033

1034

1035

1039

1040

1041

1042

1043 if (MD) {

1044 switch (S.getMethodFamily()) {

1050 break;

1051 default:

1053 break;

1054 }

1055 } else {

1057 }

1058 }

1059 break;

1061 ResultEff = ObjCInitRetE;

1063 break;

1069 ResultEff = ObjCAllocRetE;

1072 break;

1075 break;

1078 break;

1081 break;

1084 break;

1086

1087 break;

1090

1091 break;

1092 }

1093

1094

1095

1096

1097

1098 if (S.isKeywordSelector()) {

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

1100 StringRef Slot = S.getNameForSlot(i);

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

1102 if (ResultEff == ObjCInitRetE)

1104 else

1106 }

1107 }

1108 }

1109

1112 return getDefaultSummary();

1113

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

1116}

1117

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

1122

1124 ME->getType(), ObjCClassMethodSummaries);

1125}

1126

1127const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(

1131

1132

1133

1134 if (!ReceiverType.isNull())

1136 ReceiverClass = PT->getInterfaceDecl();

1137

1138

1139 if (!ReceiverClass)

1141

1142

1143

1144

1145

1148 if (!Method && ReceiverClass)

1150

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

1152 ObjCMethodSummaries);

1153}

1154

1156RetainSummaryManager::getMethodSummary(Selector S,

1159 ObjCMethodSummariesTy &CachedSummaries) {

1160

1161

1162 if (!TrackObjCAndCFObjects)

1163 return getDefaultSummary();

1164

1165

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

1167

1168 if (!Summ) {

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

1170

1171

1172 updateSummaryFromAnnotations(Summ, MD);

1173

1174

1176 }

1177

1178 return Summ;

1179}

1180

1181void RetainSummaryManager::InitializeClassMethodSummaries() {

1182 ArgEffects ScratchArgs = AF.getEmptyMap();

1183

1184

1185 addClassMethSummary("NSAssertionHandler", "currentHandler",

1187 ScratchArgs));

1188

1189

1191 addClassMethSummary("NSAutoreleasePool", "addObject",

1195}

1196

1197void RetainSummaryManager::InitializeMethodSummaries() {

1198

1199 ArgEffects ScratchArgs = AF.getEmptyMap();

1200

1201

1202 const RetainSummary *InitSumm = getPersistentSummary(

1205

1206

1207

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

1209 InitSumm);

1210

1211

1212 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,

1213 ScratchArgs);

1216

1217

1219 const RetainSummary *Summ = getPersistentSummary(

1222

1223

1224 Summ = getPersistentSummary(NoRet, ScratchArgs,

1227

1228

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

1232

1233

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

1237

1238

1239

1240

1241

1245

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

1247

1248

1249

1250

1251

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

1253

1254

1255

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

1257

1258

1259

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

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

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

1263

1264

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

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

1267

1268

1269

1270

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

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

1273 "format", "colorSpace");

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

1275}

1276

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

1282

1283 ObjCMethodSummariesTy *CachedSummaries;

1285 CachedSummaries = &ObjCMethodSummaries;

1286 else

1287 CachedSummaries = &ObjCClassMethodSummaries;

1288

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

1290}

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 ...

static bool isISLObjectRef(QualType Ty)

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

static bool hasTypedefNamed(QualType QT, StringRef Name)

static bool isOSObjectRequiredCast(StringRef S)

static ArgEffect getStopTrackingHardEquivalent(ArgEffect E)

static constexpr bool isOneOf()

static bool isOSIteratorSubclass(const Decl *D)

static QualType getCallableReturnType(const NamedDecl *ND)

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

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

static bool isOSObjectPtr(QualType QT)

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

static bool isOSObjectSubclass(const Decl *D)

static bool isOSObjectThisCast(StringRef S)

static bool isMakeCollectable(StringRef FName)

static bool isOSObjectDynamicCast(StringRef S)

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

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.

Attr - This represents one attribute.

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.

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.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

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

Represents an ObjC class declaration.

An expression that sends a message to the given Objective-C object or class.

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

ObjCMethodDecl - Represents an instance or class method declaration.

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 pointer to an Objective C object.

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)

Smart pointer class that efficiently represents Objective-C method names.

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.

ArgEffectKind getKind() const

A key identifying a summary.

RetEffect summarizes a call's retain/release behavior with respect to its return value.

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)

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

static bool isKnownSmartPointer(QualType QT)

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

Summary for a function with respect to ownership changes.

void setRetEffect(RetEffect E)

setRetEffect - Set the effect of the return value of the call.

void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e)

bool isSimple() const

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

ArgEffects getArgEffects() const

void setThisEffect(ArgEffect e)

Set the effect of the method on "this".

void setReceiverEffect(ArgEffect e)

Sets the effect on the receiver of the message.

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.

@ OMF_None

No particular method family.

Selector GetUnarySelector(StringRef name, ASTContext &Ctx)

Utility function for constructing an unary selector.

Selector GetNullarySelector(StringRef name, ASTContext &Ctx)

Utility function for constructing a nullary selector.

const FunctionProtoType * T

@ Class

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