File indexing completed on 2026-05-10 08:36:26
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
0016 #define LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H
0017
0018 #include "llvm/ADT/DenseMap.h"
0019 #include "llvm/ADT/FoldingSet.h"
0020 #include "llvm/ADT/ImmutableMap.h"
0021 #include "clang/AST/Attr.h"
0022 #include "clang/AST/DeclCXX.h"
0023 #include "clang/AST/DeclObjC.h"
0024 #include "clang/AST/ParentMap.h"
0025 #include "clang/Analysis/AnyCall.h"
0026 #include "clang/Analysis/SelectorExtras.h"
0027 #include "llvm/ADT/STLExtras.h"
0028 #include <optional>
0029
0030 using namespace clang;
0031
0032 namespace clang {
0033 namespace ento {
0034
0035
0036 enum class ObjKind {
0037
0038 CF,
0039
0040
0041 ObjC,
0042
0043
0044 AnyObj,
0045
0046
0047 Generalized,
0048
0049
0050
0051 OS
0052 };
0053
0054 enum ArgEffectKind {
0055
0056 DoNothing,
0057
0058
0059
0060 Autorelease,
0061
0062
0063 Dealloc,
0064
0065
0066 DecRef,
0067
0068
0069
0070 DecRefBridgedTransferred,
0071
0072
0073 IncRef,
0074
0075
0076
0077 UnretainedOutParameter,
0078
0079
0080
0081 RetainedOutParameter,
0082
0083
0084
0085 RetainedOutParameterOnZero,
0086
0087
0088
0089 RetainedOutParameterOnNonZero,
0090
0091
0092
0093
0094 MayEscape,
0095
0096
0097
0098 StopTracking,
0099
0100
0101
0102
0103
0104
0105
0106
0107 StopTrackingHard,
0108
0109
0110
0111
0112
0113
0114 DecRefAndStopTrackingHard,
0115 };
0116
0117
0118
0119 class ArgEffect {
0120 ArgEffectKind K;
0121 ObjKind O;
0122 public:
0123 explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
0124 : K(K), O(O) {}
0125
0126 ArgEffectKind getKind() const { return K; }
0127 ObjKind getObjKind() const { return O; }
0128
0129 ArgEffect withKind(ArgEffectKind NewK) {
0130 return ArgEffect(NewK, O);
0131 }
0132
0133 bool operator==(const ArgEffect &Other) const {
0134 return K == Other.K && O == Other.O;
0135 }
0136 };
0137
0138
0139
0140 class RetEffect {
0141 public:
0142 enum Kind {
0143
0144
0145 NoRet,
0146
0147
0148 OwnedSymbol,
0149
0150
0151
0152
0153 NotOwnedSymbol,
0154
0155
0156
0157 OwnedWhenTrackedReceiver,
0158
0159
0160
0161
0162
0163 NoRetHard
0164 };
0165
0166 private:
0167 Kind K;
0168 ObjKind O;
0169
0170 RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
0171
0172 public:
0173 Kind getKind() const { return K; }
0174
0175 ObjKind getObjKind() const { return O; }
0176
0177 bool isOwned() const {
0178 return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
0179 }
0180
0181 bool notOwned() const {
0182 return K == NotOwnedSymbol;
0183 }
0184
0185 bool operator==(const RetEffect &Other) const {
0186 return K == Other.K && O == Other.O;
0187 }
0188
0189 static RetEffect MakeOwnedWhenTrackedReceiver() {
0190 return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
0191 }
0192
0193 static RetEffect MakeOwned(ObjKind o) {
0194 return RetEffect(OwnedSymbol, o);
0195 }
0196 static RetEffect MakeNotOwned(ObjKind o) {
0197 return RetEffect(NotOwnedSymbol, o);
0198 }
0199 static RetEffect MakeNoRet() {
0200 return RetEffect(NoRet);
0201 }
0202 static RetEffect MakeNoRetHard() {
0203 return RetEffect(NoRetHard);
0204 }
0205 };
0206
0207
0208 class ObjCSummaryKey {
0209 IdentifierInfo* II;
0210 Selector S;
0211 public:
0212 ObjCSummaryKey(IdentifierInfo* ii, Selector s)
0213 : II(ii), S(s) {}
0214
0215 ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
0216 : II(d ? d->getIdentifier() : nullptr), S(s) {}
0217
0218 ObjCSummaryKey(Selector s)
0219 : II(nullptr), S(s) {}
0220
0221 IdentifierInfo *getIdentifier() const { return II; }
0222 Selector getSelector() const { return S; }
0223 };
0224
0225 }
0226 }
0227
0228 using namespace ento;
0229
0230 namespace llvm {
0231
0232
0233
0234
0235 template <> struct FoldingSetTrait<ArgEffect> {
0236 static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
0237 ID.AddInteger((unsigned) X.getKind());
0238 ID.AddInteger((unsigned) X.getObjKind());
0239 }
0240 };
0241 template <> struct FoldingSetTrait<RetEffect> {
0242 static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
0243 ID.AddInteger((unsigned) X.getKind());
0244 ID.AddInteger((unsigned) X.getObjKind());
0245 }
0246 };
0247
0248 template <> struct DenseMapInfo<ObjCSummaryKey> {
0249 static inline ObjCSummaryKey getEmptyKey() {
0250 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
0251 DenseMapInfo<Selector>::getEmptyKey());
0252 }
0253
0254 static inline ObjCSummaryKey getTombstoneKey() {
0255 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
0256 DenseMapInfo<Selector>::getTombstoneKey());
0257 }
0258
0259 static unsigned getHashValue(const ObjCSummaryKey &V) {
0260 typedef std::pair<IdentifierInfo*, Selector> PairTy;
0261 return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
0262 V.getSelector()));
0263 }
0264
0265 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
0266 return LHS.getIdentifier() == RHS.getIdentifier() &&
0267 LHS.getSelector() == RHS.getSelector();
0268 }
0269
0270 };
0271
0272 }
0273
0274
0275 namespace clang {
0276 namespace ento {
0277
0278
0279
0280 typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
0281
0282
0283 class RetainSummary {
0284
0285
0286
0287 ArgEffects Args;
0288
0289
0290
0291 ArgEffect DefaultArgEffect;
0292
0293
0294
0295 ArgEffect Receiver;
0296
0297
0298 ArgEffect This;
0299
0300
0301
0302 RetEffect Ret;
0303
0304 public:
0305 RetainSummary(ArgEffects A,
0306 RetEffect R,
0307 ArgEffect defaultEff,
0308 ArgEffect ReceiverEff,
0309 ArgEffect ThisEff)
0310 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
0311 This(ThisEff), Ret(R) {}
0312
0313
0314
0315 ArgEffect getArg(unsigned idx) const {
0316 if (const ArgEffect *AE = Args.lookup(idx))
0317 return *AE;
0318
0319 return DefaultArgEffect;
0320 }
0321
0322 void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
0323 Args = af.add(Args, idx, e);
0324 }
0325
0326
0327 void setDefaultArgEffect(ArgEffect E) {
0328 DefaultArgEffect = E;
0329 }
0330
0331
0332 RetEffect getRetEffect() const { return Ret; }
0333
0334
0335 void setRetEffect(RetEffect E) { Ret = E; }
0336
0337
0338
0339 void setReceiverEffect(ArgEffect e) { Receiver = e; }
0340
0341
0342
0343 ArgEffect getReceiverEffect() const { return Receiver; }
0344
0345
0346
0347 ArgEffect getThisEffect() const { return This; }
0348
0349 ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
0350
0351
0352 void setThisEffect(ArgEffect e) { This = e; }
0353
0354 bool isNoop() const {
0355 return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
0356 && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
0357 && Args.isEmpty();
0358 }
0359
0360
0361
0362
0363 bool operator==(const RetainSummary &Other) const {
0364 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
0365 Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
0366 }
0367
0368
0369 void Profile(llvm::FoldingSetNodeID& ID) const {
0370 ID.Add(Args);
0371 ID.Add(DefaultArgEffect);
0372 ID.Add(Receiver);
0373 ID.Add(This);
0374 ID.Add(Ret);
0375 }
0376
0377
0378 bool isSimple() const {
0379 return Args.isEmpty();
0380 }
0381
0382 ArgEffects getArgEffects() const { return Args; }
0383
0384 private:
0385 ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
0386
0387 friend class RetainSummaryManager;
0388 };
0389
0390 class ObjCSummaryCache {
0391 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
0392 MapTy M;
0393 public:
0394 ObjCSummaryCache() {}
0395
0396 const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
0397
0398
0399 ObjCSummaryKey K(D, S);
0400 MapTy::iterator I = M.find(K);
0401
0402 if (I != M.end())
0403 return I->second;
0404 if (!D)
0405 return nullptr;
0406
0407
0408
0409
0410
0411
0412
0413 for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
0414 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
0415 break;
0416
0417 if (!C)
0418 return nullptr;
0419 }
0420
0421
0422
0423 const RetainSummary *Summ = I->second;
0424 M[K] = Summ;
0425 return Summ;
0426 }
0427
0428 const RetainSummary *find(IdentifierInfo* II, Selector S) {
0429
0430
0431 MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
0432
0433 if (I == M.end())
0434 I = M.find(ObjCSummaryKey(S));
0435
0436 return I == M.end() ? nullptr : I->second;
0437 }
0438
0439 const RetainSummary *& operator[](ObjCSummaryKey K) {
0440 return M[K];
0441 }
0442
0443 const RetainSummary *& operator[](Selector S) {
0444 return M[ ObjCSummaryKey(S) ];
0445 }
0446 };
0447
0448 class RetainSummaryTemplate;
0449
0450 class RetainSummaryManager {
0451 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
0452 FuncSummariesTy;
0453
0454 typedef ObjCSummaryCache ObjCMethodSummariesTy;
0455
0456 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
0457
0458
0459 ASTContext &Ctx;
0460
0461
0462 const bool ARCEnabled;
0463
0464
0465 const bool TrackObjCAndCFObjects;
0466
0467
0468 const bool TrackOSObjects;
0469
0470
0471 FuncSummariesTy FuncSummaries;
0472
0473
0474
0475 ObjCMethodSummariesTy ObjCClassMethodSummaries;
0476
0477
0478 ObjCMethodSummariesTy ObjCMethodSummaries;
0479
0480
0481
0482 llvm::BumpPtrAllocator BPAlloc;
0483
0484
0485 ArgEffects::Factory AF;
0486
0487
0488
0489 RetEffect ObjCAllocRetE;
0490
0491
0492
0493 RetEffect ObjCInitRetE;
0494
0495
0496
0497 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
0498
0499
0500 const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
0501
0502
0503 const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
0504
0505
0506 const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
0507
0508
0509 const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
0510
0511
0512 const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
0513
0514 const RetainSummary *getUnarySummary(const FunctionType* FT,
0515 ArgEffectKind AE);
0516
0517 const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
0518 const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
0519 const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
0520
0521 const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
0522
0523 const RetainSummary *
0524 getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
0525 ArgEffect ReceiverEff = ArgEffect(DoNothing),
0526 ArgEffect DefaultEff = ArgEffect(MayEscape),
0527 ArgEffect ThisEff = ArgEffect(DoNothing)) {
0528 RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
0529 return getPersistentSummary(Summ);
0530 }
0531
0532 const RetainSummary *getDoNothingSummary() {
0533 return getPersistentSummary(RetEffect::MakeNoRet(),
0534 ArgEffects(AF.getEmptyMap()),
0535 ArgEffect(DoNothing), ArgEffect(DoNothing));
0536 }
0537
0538 const RetainSummary *getDefaultSummary() {
0539 return getPersistentSummary(RetEffect::MakeNoRet(),
0540 ArgEffects(AF.getEmptyMap()),
0541 ArgEffect(DoNothing), ArgEffect(MayEscape));
0542 }
0543
0544 const RetainSummary *getPersistentStopSummary() {
0545 return getPersistentSummary(
0546 RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
0547 ArgEffect(StopTracking), ArgEffect(StopTracking));
0548 }
0549
0550 void InitializeClassMethodSummaries();
0551 void InitializeMethodSummaries();
0552
0553 void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
0554 ObjCClassMethodSummaries[S] = Summ;
0555 }
0556
0557 void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
0558 ObjCMethodSummaries[S] = Summ;
0559 }
0560
0561 void addClassMethSummary(const char* Cls, const char* name,
0562 const RetainSummary *Summ, bool isNullary = true) {
0563 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
0564 Selector S = isNullary ? GetNullarySelector(name, Ctx)
0565 : GetUnarySelector(name, Ctx);
0566 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
0567 }
0568
0569 void addInstMethSummary(const char* Cls, const char* nullaryName,
0570 const RetainSummary *Summ) {
0571 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
0572 Selector S = GetNullarySelector(nullaryName, Ctx);
0573 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
0574 }
0575
0576 template <typename... Keywords>
0577 void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
0578 const RetainSummary *Summ, Keywords *... Kws) {
0579 Selector S = getKeywordSelector(Ctx, Kws...);
0580 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
0581 }
0582
0583 template <typename... Keywords>
0584 void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
0585 Keywords *... Kws) {
0586 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
0587 }
0588
0589 template <typename... Keywords>
0590 void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
0591 Keywords *... Kws) {
0592 addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
0593 Kws...);
0594 }
0595
0596 template <typename... Keywords>
0597 void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
0598 Keywords *... Kws) {
0599 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
0600 }
0601
0602 const RetainSummary * generateSummary(const FunctionDecl *FD,
0603 bool &AllowAnnotations);
0604
0605
0606 const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
0607 StringRef FName, QualType RetTy);
0608
0609
0610 const RetainSummary *getSummaryForObjCOrCFObject(
0611 const FunctionDecl *FD,
0612 StringRef FName,
0613 QualType RetTy,
0614 const FunctionType *FT,
0615 bool &AllowAnnotations);
0616
0617
0618
0619
0620 bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
0621 const NamedDecl *FD,
0622 RetainSummaryTemplate &Template);
0623
0624 public:
0625 RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
0626 bool trackOSObjects)
0627 : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
0628 TrackObjCAndCFObjects(trackObjCAndCFObjects),
0629 TrackOSObjects(trackOSObjects), AF(BPAlloc),
0630 ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
0631 : RetEffect::MakeOwned(ObjKind::ObjC)),
0632 ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
0633 : RetEffect::MakeOwnedWhenTrackedReceiver()) {
0634 InitializeClassMethodSummaries();
0635 InitializeMethodSummaries();
0636 }
0637
0638 enum class BehaviorSummary {
0639
0640 NoOp,
0641
0642
0643 Identity,
0644
0645
0646 IdentityThis,
0647
0648
0649 IdentityOrZero
0650 };
0651
0652 std::optional<BehaviorSummary>
0653 canEval(const CallExpr *CE, const FunctionDecl *FD,
0654 bool &hasTrustedImplementationAnnotation);
0655
0656
0657
0658 static bool isKnownSmartPointer(QualType QT);
0659
0660 bool isTrustedReferenceCountImplementation(const Decl *FD);
0661
0662 const RetainSummary *getSummary(AnyCall C,
0663 bool HasNonZeroCallbackArg=false,
0664 bool IsReceiverUnconsumedSelf=false,
0665 QualType ReceiverType={});
0666
0667 RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
0668
0669 private:
0670
0671
0672
0673 const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
0674
0675 const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
0676
0677 const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
0678 const ObjCMethodDecl *MD,
0679 QualType RetTy,
0680 ObjCMethodSummariesTy &CachedSummaries);
0681
0682 const RetainSummary *
0683 getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
0684
0685 const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
0686
0687 const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
0688 Selector S, QualType RetTy);
0689
0690
0691 std::optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
0692 const Decl *D);
0693
0694 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
0695 const ObjCMethodDecl *MD);
0696
0697 void updateSummaryFromAnnotations(const RetainSummary *&Summ,
0698 const FunctionDecl *FD);
0699
0700 const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
0701 AnyCall &C);
0702
0703
0704
0705
0706
0707
0708
0709
0710
0711
0712
0713
0714
0715 void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
0716
0717
0718 void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
0719
0720
0721
0722
0723
0724
0725
0726
0727 template <class T>
0728 std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
0729
0730 template <class T1, class T2, class... Others>
0731 std::optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
0732
0733 friend class RetainSummaryTemplate;
0734 };
0735
0736
0737
0738
0739
0740
0741 class RetainSummaryTemplate {
0742 RetainSummaryManager &Manager;
0743 const RetainSummary *&RealSummary;
0744 RetainSummary ScratchSummary;
0745 bool Accessed;
0746 public:
0747 RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
0748 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
0749
0750 ~RetainSummaryTemplate() {
0751 if (Accessed)
0752 RealSummary = Manager.getPersistentSummary(ScratchSummary);
0753 }
0754
0755 RetainSummary &operator*() {
0756 Accessed = true;
0757 return ScratchSummary;
0758 }
0759
0760 RetainSummary *operator->() {
0761 Accessed = true;
0762 return &ScratchSummary;
0763 }
0764 };
0765
0766 }
0767 }
0768
0769 #endif