34 #include "llvm/ADT/DenseMap.h" 35 #include "llvm/ADT/FoldingSet.h" 36 #include "llvm/ADT/ImmutableList.h" 37 #include "llvm/ADT/ImmutableMap.h" 38 #include "llvm/ADT/STLExtras.h" 39 #include "llvm/ADT/SmallString.h" 40 #include "llvm/ADT/StringExtras.h" 44 using namespace clang;
46 using namespace objc_retain;
47 using llvm::StrInStrNoCase;
56 ID.AddInteger((
unsigned) X);
61 ID.AddInteger((
unsigned) X.
getKind());
73 typedef llvm::ImmutableMap<unsigned,ArgEffect>
ArgEffects;
102 enum class IvarAccessHistory {
105 ReleasedAfterDirectAccess
119 unsigned RawKind : 5;
124 unsigned RawObjectKind : 2;
135 unsigned RawIvarAccessHistory : 2;
138 IvarAccessHistory IvarAccess)
139 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
140 RawObjectKind(static_cast<unsigned>(o)),
141 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
142 assert(
getKind() == k &&
"not enough bits for the kind");
143 assert(getObjKind() == o &&
"not enough bits for the object kind");
144 assert(getIvarAccessHistory() == IvarAccess &&
"not enough bits");
154 unsigned getCount()
const {
return Cnt; }
155 unsigned getAutoreleaseCount()
const {
return ACnt; }
156 unsigned getCombinedCounts()
const {
return Cnt + ACnt; }
161 void setCount(
unsigned i) {
164 void setAutoreleaseCount(
unsigned i) {
168 QualType getType()
const {
return T; }
175 IvarAccessHistory getIvarAccessHistory()
const {
176 return static_cast<IvarAccessHistory
>(RawIvarAccessHistory);
179 bool isOwned()
const {
183 bool isNotOwned()
const {
187 bool isReturnedOwned()
const {
188 return getKind() == ReturnedOwned;
191 bool isReturnedNotOwned()
const {
192 return getKind() == ReturnedNotOwned;
200 unsigned Count = 1) {
209 unsigned Count = 0) {
213 RefVal operator-(
size_t i)
const {
214 return RefVal(
getKind(), getObjKind(), getCount() - i,
215 getAutoreleaseCount(), getType(), getIvarAccessHistory());
218 RefVal operator+(
size_t i)
const {
219 return RefVal(
getKind(), getObjKind(), getCount() + i,
220 getAutoreleaseCount(), getType(), getIvarAccessHistory());
223 RefVal operator^(
Kind k)
const {
224 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
225 getType(), getIvarAccessHistory());
228 RefVal autorelease()
const {
229 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
230 getType(), getIvarAccessHistory());
233 RefVal withIvarAccess()
const {
235 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
236 getType(), IvarAccessHistory::AccessedDirectly);
239 RefVal releaseViaIvar()
const {
240 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
241 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
242 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
247 bool hasSameState(
const RefVal &
X)
const {
248 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
249 getIvarAccessHistory() == X.getIvarAccessHistory();
253 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
256 void Profile(llvm::FoldingSetNodeID&
ID)
const {
258 ID.AddInteger(RawKind);
261 ID.AddInteger(RawObjectKind);
262 ID.AddInteger(RawIvarAccessHistory);
265 void print(raw_ostream &Out)
const;
268 void RefVal::print(raw_ostream &Out)
const {
270 Out <<
"Tracked " << T.getAsString() <<
'/';
273 default: llvm_unreachable(
"Invalid RefVal kind");
276 unsigned cnt = getCount();
277 if (cnt) Out <<
" (+ " << cnt <<
")";
283 unsigned cnt = getCount();
284 if (cnt) Out <<
" (+ " << cnt <<
")";
288 case ReturnedOwned: {
289 Out <<
"ReturnedOwned";
290 unsigned cnt = getCount();
291 if (cnt) Out <<
" (+ " << cnt <<
")";
295 case ReturnedNotOwned: {
296 Out <<
"ReturnedNotOwned";
297 unsigned cnt = getCount();
298 if (cnt) Out <<
" (+ " << cnt <<
")";
307 Out <<
"-dealloc (GC)";
310 case ErrorDeallocNotOwned:
311 Out <<
"-dealloc (not-owned)";
318 case ErrorLeakReturned:
319 Out <<
"Leaked (Bad naming)";
322 case ErrorGCLeakReturned:
323 Out <<
"Leaked (GC-ed at return)";
326 case ErrorUseAfterRelease:
327 Out <<
"Use-After-Release [ERROR]";
330 case ErrorReleaseNotOwned:
331 Out <<
"Release of Not-Owned [ERROR]";
334 case RefVal::ErrorOverAutorelease:
335 Out <<
"Over-autoreleased";
338 case RefVal::ErrorReturnedNotOwned:
339 Out <<
"Non-owned object returned instead of owned";
343 switch (getIvarAccessHistory()) {
346 case IvarAccessHistory::AccessedDirectly:
347 Out <<
" [direct ivar access]";
349 case IvarAccessHistory::ReleasedAfterDirectAccess:
350 Out <<
" [released after direct ivar access]";
354 Out <<
" [autorelease -" << ACnt <<
']';
367 return State->get<RefBindings>(Sym);
372 return State->set<RefBindings>(Sym, Val);
376 return State->remove<RefBindings>(Sym);
384 class RetainSummary {
405 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
410 if (
const ArgEffect *AE = Args.lookup(idx))
413 return DefaultArgEffect;
417 Args = af.add(Args, idx, e);
422 DefaultArgEffect = E;
426 RetEffect getRetEffect()
const {
return Ret; }
429 void setRetEffect(
RetEffect E) { Ret = E; }
433 void setReceiverEffect(
ArgEffect e) { Receiver = e; }
437 ArgEffect getReceiverEffect()
const {
return Receiver; }
442 bool operator==(
const RetainSummary &Other)
const {
443 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
444 Receiver == Other.Receiver && Ret == Other.Ret;
448 void Profile(llvm::FoldingSetNodeID&
ID)
const {
450 ID.Add(DefaultArgEffect);
456 bool isSimple()
const {
457 return Args.isEmpty();
461 ArgEffects getArgEffects()
const {
return Args; }
462 ArgEffect getDefaultArgEffect()
const {
return DefaultArgEffect; }
464 friend class RetainSummaryManager;
465 friend class RetainCountChecker;
474 class ObjCSummaryKey {
485 : II(
nullptr), S(s) {}
488 Selector getSelector()
const {
return S; }
505 typedef std::pair<IdentifierInfo*, Selector> PairTy;
510 static bool isEqual(
const ObjCSummaryKey& LHS,
const ObjCSummaryKey& RHS) {
511 return LHS.getIdentifier() == RHS.getIdentifier() &&
512 LHS.getSelector() == RHS.getSelector();
519 class ObjCSummaryCache {
520 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *>
MapTy;
523 ObjCSummaryCache() {}
528 ObjCSummaryKey K(D, S);
529 MapTy::iterator I = M.find(K);
543 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
552 const RetainSummary *Summ = I->second;
560 MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
563 I = M.find(ObjCSummaryKey(S));
565 return I == M.end() ? nullptr : I->second;
568 const RetainSummary *& operator[](ObjCSummaryKey K) {
572 const RetainSummary *& operator[](
Selector S) {
573 return M[ ObjCSummaryKey(S) ];
583 class RetainSummaryManager {
589 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
592 typedef ObjCSummaryCache ObjCMethodSummariesTy;
594 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
604 const bool GCEnabled;
607 const bool ARCEnabled;
610 FuncSummariesTy FuncSummaries;
614 ObjCMethodSummariesTy ObjCClassMethodSummaries;
617 ObjCMethodSummariesTy ObjCMethodSummaries;
621 llvm::BumpPtrAllocator BPAlloc;
639 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
649 enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
651 const RetainSummary *getUnarySummary(
const FunctionType* FT,
654 const RetainSummary *getCFSummaryCreateRule(
const FunctionDecl *FD);
655 const RetainSummary *getCFSummaryGetRule(
const FunctionDecl *FD);
656 const RetainSummary *getCFCreateGetRuleSummary(
const FunctionDecl *FD);
658 const RetainSummary *getPersistentSummary(
const RetainSummary &OldSumm);
660 const RetainSummary *getPersistentSummary(
RetEffect RetEff,
663 RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
664 return getPersistentSummary(Summ);
667 const RetainSummary *getDoNothingSummary() {
671 const RetainSummary *getDefaultSummary() {
676 const RetainSummary *getPersistentStopSummary() {
681 void InitializeClassMethodSummaries();
682 void InitializeMethodSummaries();
684 void addNSObjectClsMethSummary(
Selector S,
const RetainSummary *Summ) {
685 ObjCClassMethodSummaries[S] = Summ;
688 void addNSObjectMethSummary(
Selector S,
const RetainSummary *Summ) {
689 ObjCMethodSummaries[S] = Summ;
692 void addClassMethSummary(
const char* Cls,
const char* name,
693 const RetainSummary *Summ,
bool isNullary =
true) {
697 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
700 void addInstMethSummary(
const char* Cls,
const char* nullaryName,
701 const RetainSummary *Summ) {
704 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
707 template <
typename... Keywords>
708 void addMethodSummary(
IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
709 const RetainSummary *Summ, Keywords *... Kws) {
711 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
714 template <
typename... Keywords>
715 void addInstMethSummary(
const char *Cls,
const RetainSummary *Summ,
717 addMethodSummary(&Ctx.
Idents.
get(Cls), ObjCMethodSummaries, Summ, Kws...);
720 template <
typename... Keywords>
721 void addClsMethSummary(
const char *Cls,
const RetainSummary *Summ,
723 addMethodSummary(&Ctx.
Idents.
get(Cls), ObjCClassMethodSummaries, Summ,
727 template <
typename... Keywords>
728 void addClsMethSummary(
IdentifierInfo *II,
const RetainSummary *Summ,
730 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
735 RetainSummaryManager(
ASTContext &ctx,
bool gcenabled,
bool usesARC)
737 GCEnabled(gcenabled),
739 AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
740 ObjCAllocRetE(gcenabled
744 ObjCInitRetE(gcenabled
748 InitializeClassMethodSummaries();
749 InitializeMethodSummaries();
752 const RetainSummary *getSummary(
const CallEvent &Call,
755 const RetainSummary *getFunctionSummary(
const FunctionDecl *FD);
760 ObjCMethodSummariesTy &CachedSummaries);
762 const RetainSummary *getInstanceMethodSummary(
const ObjCMethodCall &M,
765 const RetainSummary *getClassMethodSummary(
const ObjCMethodCall &M) {
770 M.getResultType(), ObjCClassMethodSummaries);
780 ObjCMethodSummariesTy *CachedSummaries;
782 CachedSummaries = &ObjCMethodSummaries;
784 CachedSummaries = &ObjCClassMethodSummaries;
786 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
789 const RetainSummary *getStandardMethodSummary(
const ObjCMethodDecl *MD,
796 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
799 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
802 void updateSummaryForCall(
const RetainSummary *&Summ,
805 bool isGCEnabled()
const {
return GCEnabled; }
807 bool isARCEnabled()
const {
return ARCEnabled; }
809 bool isARCorGCEnabled()
const {
return GCEnabled || ARCEnabled; }
811 RetEffect getObjAllocRetEffect()
const {
return ObjCAllocRetE; }
813 friend class RetainSummaryTemplate;
820 class RetainSummaryTemplate {
821 RetainSummaryManager &Manager;
822 const RetainSummary *&RealSummary;
823 RetainSummary ScratchSummary;
826 RetainSummaryTemplate(
const RetainSummary *&real, RetainSummaryManager &mgr)
827 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(
false) {}
829 ~RetainSummaryTemplate() {
831 RealSummary = Manager.getPersistentSummary(ScratchSummary);
836 return ScratchSummary;
839 RetainSummary *operator->() {
841 return &ScratchSummary;
851 ArgEffects RetainSummaryManager::getArgEffects() {
853 ScratchArgs = AF.getEmptyMap();
857 const RetainSummary *
858 RetainSummaryManager::getPersistentSummary(
const RetainSummary &OldSumm) {
860 if (OldSumm.isSimple()) {
861 llvm::FoldingSetNodeID
ID;
865 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
868 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
869 new (N) CachedSummaryNode(OldSumm);
870 SimpleSummaries.InsertNode(N, Pos);
873 return &N->getValue();
876 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
877 new (Summ) RetainSummary(OldSumm);
886 return FName.startswith_lower(
"retain") || FName.endswith_lower(
"retain");
890 return FName.startswith_lower(
"release") || FName.endswith_lower(
"release");
894 return FName.startswith_lower(
"autorelease") ||
895 FName.endswith_lower(
"autorelease");
901 return FName.find_lower(
"MakeCollectable") != StringRef::npos;
928 llvm_unreachable(
"Unknown ArgEffect kind");
931 void RetainSummaryManager::updateSummaryForCall(
const RetainSummary *&S,
939 ArgEffects CustomArgEffects = S->getArgEffects();
940 for (ArgEffects::iterator I = CustomArgEffects.begin(),
941 E = CustomArgEffects.end();
944 if (Translated != DefEffect)
945 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
959 if (Name->isStr(
"CGBitmapContextCreateWithData") ||
960 Name->isStr(
"dispatch_data_create"))
961 RE = S->getRetEffect();
965 S = getPersistentSummary(RE, RecEffect, DefEffect);
981 if (MC->getMethodFamily() ==
OMF_init && MC->isReceiverSelfOrSuper()) {
985 const Expr *ME = MC->getOriginExpr();
989 RetainSummaryTemplate ModifiableSummaryTemplate(S, *
this);
990 ModifiableSummaryTemplate->setReceiverEffect(
DoNothing);
997 const RetainSummary *
998 RetainSummaryManager::getSummary(
const CallEvent &Call,
1000 const RetainSummary *Summ;
1003 Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
1012 return getPersistentStopSummary();
1016 Summ = getInstanceMethodSummary(Msg, State);
1018 Summ = getClassMethodSummary(Msg);
1023 updateSummaryForCall(Summ, Call);
1025 assert(Summ &&
"Unknown call type?");
1029 const RetainSummary *
1030 RetainSummaryManager::getFunctionSummary(
const FunctionDecl *FD) {
1033 return getDefaultSummary();
1036 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
1037 if (I != FuncSummaries.end())
1041 const RetainSummary *S =
nullptr;
1042 bool AllowAnnotations =
true;
1047 S = getPersistentStopSummary();
1058 StringRef FName = II->
getName();
1062 FName = FName.substr(FName.find_first_not_of(
'_'));
1070 assert(ScratchArgs.isEmpty());
1072 if (FName ==
"pthread_create" || FName ==
"pthread_setspecific") {
1075 S = getPersistentStopSummary();
1076 }
else if (FName ==
"NSMakeCollectable") {
1079 ? getUnarySummary(FT, cfmakecollectable)
1080 : getPersistentStopSummary();
1083 AllowAnnotations =
false;
1084 }
else if (FName ==
"CFPlugInInstanceCreate") {
1086 }
else if (FName ==
"IORegistryEntrySearchCFProperty" 1087 || (RetTyName ==
"CFMutableDictionaryRef" && (
1088 FName ==
"IOBSDNameMatching" ||
1089 FName ==
"IOServiceMatching" ||
1090 FName ==
"IOServiceNameMatching" ||
1091 FName ==
"IORegistryEntryIDMatching" ||
1092 FName ==
"IOOpenFirmwarePathMatching" 1098 }
else if (FName ==
"IOServiceGetMatchingService" ||
1099 FName ==
"IOServiceGetMatchingServices") {
1103 ScratchArgs = AF.add(ScratchArgs, 1,
DecRef);
1105 }
else if (FName ==
"IOServiceAddNotification" ||
1106 FName ==
"IOServiceAddMatchingNotification") {
1109 ScratchArgs = AF.add(ScratchArgs, 2,
DecRef);
1111 }
else if (FName ==
"CVPixelBufferCreateWithBytes") {
1120 }
else if (FName ==
"CGBitmapContextCreateWithData") {
1128 }
else if (FName ==
"CVPixelBufferCreateWithPlanarBytes") {
1136 }
else if (FName ==
"VTCompressionSessionEncodeFrame") {
1144 }
else if (FName ==
"dispatch_set_context" ||
1145 FName ==
"xpc_connection_set_context") {
1154 }
else if (FName.startswith(
"NSLog")) {
1155 S = getDoNothingSummary();
1156 }
else if (FName.startswith(
"NS") &&
1157 (FName.find(
"Insert") != StringRef::npos)) {
1173 S = getUnarySummary(FT, cfretain);
1178 AllowAnnotations =
false;
1180 S = getUnarySummary(FT, cfautorelease);
1183 AllowAnnotations =
false;
1185 S = getUnarySummary(FT, cfmakecollectable);
1186 AllowAnnotations =
false;
1188 S = getCFCreateGetRuleSummary(FD);
1198 S = getUnarySummary(FT, cfretain);
1200 S = getCFCreateGetRuleSummary(FD);
1209 S = getCFCreateGetRuleSummary(FD);
1213 if (FD->
hasAttr<CFAuditedTransferAttr>()) {
1214 S = getCFCreateGetRuleSummary(FD);
1223 if (FName.size() >= 2 &&
1224 FName[0] ==
'C' && (FName[1] ==
'F' || FName[1] ==
'G')) {
1226 FName = FName.substr(FName.startswith(
"CGCF") ? 4 : 2);
1229 S = getUnarySummary(FT, cfrelease);
1231 assert (ScratchArgs.isEmpty());
1247 ArgEffect E = (StrInStrNoCase(FName,
"InsertValue") != StringRef::npos||
1248 StrInStrNoCase(FName,
"AddValue") != StringRef::npos ||
1249 StrInStrNoCase(FName,
"SetValue") != StringRef::npos ||
1250 StrInStrNoCase(FName,
"AppendValue") != StringRef::npos||
1251 StrInStrNoCase(FName,
"SetAttribute") != StringRef::npos)
1262 S = getDefaultSummary();
1265 if (AllowAnnotations)
1266 updateSummaryFromAnnotations(S, FD);
1268 FuncSummaries[FD] = S;
1272 const RetainSummary *
1273 RetainSummaryManager::getCFCreateGetRuleSummary(
const FunctionDecl *FD) {
1275 return getCFSummaryCreateRule(FD);
1277 return getCFSummaryGetRule(FD);
1280 const RetainSummary *
1281 RetainSummaryManager::getUnarySummary(
const FunctionType* FT,
1282 UnaryFuncKind func) {
1288 return getPersistentStopSummary();
1290 assert (ScratchArgs.isEmpty());
1294 case cfretain: Effect =
IncRef;
break;
1295 case cfrelease: Effect =
DecRef;
break;
1300 ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1304 const RetainSummary *
1305 RetainSummaryManager::getCFSummaryCreateRule(
const FunctionDecl *FD) {
1306 assert (ScratchArgs.isEmpty());
1311 const RetainSummary *
1312 RetainSummaryManager::getCFSummaryGetRule(
const FunctionDecl *FD) {
1313 assert (ScratchArgs.isEmpty());
1321 if (Ann->getAnnotation() == rcAnnotation)
1345 RetainSummaryManager::getRetEffectFromAnnotations(
QualType RetTy,
1348 if (D->
hasAttr<NSReturnsRetainedAttr>())
1349 return ObjCAllocRetE;
1351 if (D->
hasAttr<NSReturnsNotRetainedAttr>() ||
1352 D->
hasAttr<NSReturnsAutoreleasedAttr>())
1359 if (D->
hasAttr<CFReturnsRetainedAttr>())
1364 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
1371 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1376 assert(Summ &&
"Must have a summary to add annotations to.");
1377 RetainSummaryTemplate Template(Summ, *
this);
1380 unsigned parm_idx = 0;
1382 pe = FD->
param_end(); pi != pe; ++pi, ++parm_idx) {
1384 if (pd->
hasAttr<NSConsumedAttr>())
1385 Template->addArg(AF, parm_idx,
DecRefMsg);
1386 else if (pd->
hasAttr<CFConsumedAttr>() ||
1388 Template->addArg(AF, parm_idx,
DecRef);
1389 else if (pd->
hasAttr<CFReturnsRetainedAttr>() ||
1395 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1405 Template->setRetEffect(*RetE);
1409 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1414 assert(Summ &&
"Must have a valid summary to add annotations to");
1415 RetainSummaryTemplate Template(Summ, *
this);
1418 if (MD->
hasAttr<NSConsumesSelfAttr>())
1422 unsigned parm_idx = 0;
1425 pi != pe; ++pi, ++parm_idx) {
1427 if (pd->
hasAttr<NSConsumedAttr>())
1428 Template->addArg(AF, parm_idx,
DecRefMsg);
1429 else if (pd->
hasAttr<CFConsumedAttr>()) {
1430 Template->addArg(AF, parm_idx,
DecRef);
1431 }
else if (pd->
hasAttr<CFReturnsRetainedAttr>()) {
1436 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1446 Template->setRetEffect(*RetE);
1449 const RetainSummary *
1450 RetainSummaryManager::getStandardMethodSummary(
const ObjCMethodDecl *MD,
1489 ResultEff = ObjCInitRetE;
1497 ResultEff = ObjCAllocRetE;
1527 for (
unsigned i = 0, e = S.
getNumArgs(); i != e; ++i) {
1529 if (Slot.substr(Slot.size() - 8).equals_lower(
"delegate")) {
1530 if (ResultEff == ObjCInitRetE)
1538 if (ScratchArgs.isEmpty() && ReceiverEff ==
DoNothing &&
1540 return getDefaultSummary();
1542 return getPersistentSummary(ResultEff, ReceiverEff,
MayEscape);
1545 const RetainSummary *
1546 RetainSummaryManager::getInstanceMethodSummary(
const ObjCMethodCall &Msg,
1560 ReceiverClass = PT->getInterfaceDecl();
1572 if (!Method && ReceiverClass)
1575 return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1576 ObjCMethodSummaries);
1579 const RetainSummary *
1582 ObjCMethodSummariesTy &CachedSummaries) {
1585 const RetainSummary *Summ = CachedSummaries.find(ID, S);
1588 Summ = getStandardMethodSummary(MD, S, RetTy);
1591 updateSummaryFromAnnotations(Summ, MD);
1594 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1600 void RetainSummaryManager::InitializeClassMethodSummaries() {
1601 assert(ScratchArgs.isEmpty());
1603 addClassMethSummary(
"NSAssertionHandler",
"currentHandler",
1607 ScratchArgs = AF.add(ScratchArgs, 0,
Autorelease);
1608 addClassMethSummary(
"NSAutoreleasePool",
"addObject",
1613 void RetainSummaryManager::InitializeMethodSummaries() {
1615 assert (ScratchArgs.isEmpty());
1619 const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE,
DecRefMsg);
1628 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1629 const RetainSummary *CFAllocSumm =
1634 const RetainSummary *Summ = getPersistentSummary(NoRet,
IncRefMsg);
1638 Summ = getPersistentSummary(NoRet,
DecRefMsg);
1642 Summ = getPersistentSummary(NoRet,
Dealloc);
1659 addClassMethSummary(
"NSWindow",
"alloc", NoTrackYet);
1665 addClassMethSummary(
"NSPanel",
"alloc", NoTrackYet);
1670 addClassMethSummary(
"NSNull",
"null", NoTrackYet);
1674 addClassMethSummary(
"NSAutoreleasePool",
"alloc", NoTrackYet);
1675 addClassMethSummary(
"NSAutoreleasePool",
"allocWithZone", NoTrackYet,
false);
1676 addClassMethSummary(
"NSAutoreleasePool",
"new", NoTrackYet);
1679 addInstMethSummary(
"QCRenderer", AllocSumm,
"createSnapshotImageOfType");
1680 addInstMethSummary(
"QCView", AllocSumm,
"createSnapshotImageOfType");
1685 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect");
1686 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect",
1687 "format",
"colorSpace");
1688 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGLayerWithSize",
"info");
1695 typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1702 class CFRefBug :
public BugType {
1704 CFRefBug(
const CheckerBase *checker, StringRef name)
1710 virtual const char *getDescription()
const = 0;
1712 virtual bool isLeak()
const {
return false; }
1715 class UseAfterRelease :
public CFRefBug {
1718 : CFRefBug(checker,
"Use-after-release") {}
1720 const char *getDescription()
const override {
1721 return "Reference-counted object is used after it is released";
1725 class BadRelease :
public CFRefBug {
1727 BadRelease(
const CheckerBase *checker) : CFRefBug(checker,
"Bad release") {}
1729 const char *getDescription()
const override {
1730 return "Incorrect decrement of the reference count of an object that is " 1731 "not owned at this point by the caller";
1735 class DeallocGC :
public CFRefBug {
1738 : CFRefBug(checker,
"-dealloc called while using garbage collection") {}
1740 const char *getDescription()
const override {
1741 return "-dealloc called while using garbage collection";
1745 class DeallocNotOwned :
public CFRefBug {
1748 : CFRefBug(checker,
"-dealloc sent to non-exclusively owned object") {}
1750 const char *getDescription()
const override {
1751 return "-dealloc sent to object that may be referenced elsewhere";
1755 class OverAutorelease :
public CFRefBug {
1758 : CFRefBug(checker,
"Object autoreleased too many times") {}
1760 const char *getDescription()
const override {
1761 return "Object autoreleased too many times";
1765 class ReturnedNotOwnedForOwned :
public CFRefBug {
1767 ReturnedNotOwnedForOwned(
const CheckerBase *checker)
1768 : CFRefBug(checker,
"Method should return an owned object") {}
1770 const char *getDescription()
const override {
1771 return "Object with a +0 retain count returned to caller where a +1 " 1772 "(owning) retain count is expected";
1776 class Leak :
public CFRefBug {
1778 Leak(
const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
1780 setSuppressOnSink(
true);
1783 const char *getDescription()
const override {
return ""; }
1785 bool isLeak()
const override {
return true; }
1794 const SummaryLogTy &SummaryLog;
1798 CFRefReportVisitor(
SymbolRef sym,
bool gcEnabled,
const SummaryLogTy &
log)
1799 : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1801 void Profile(llvm::FoldingSetNodeID &ID)
const override {
1807 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
1817 class CFRefLeakReportVisitor :
public CFRefReportVisitor {
1819 CFRefLeakReportVisitor(
SymbolRef sym,
bool GCEnabled,
1820 const SummaryLogTy &
log)
1821 : CFRefReportVisitor(sym, GCEnabled, log) {}
1829 void addGCModeDescription(
const LangOptions &LOpts,
bool GCEnabled);
1832 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1834 bool registerVisitor =
true)
1836 if (registerVisitor)
1837 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1838 addGCModeDescription(LOpts, GCEnabled);
1841 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1844 :
BugReport(D, D.getDescription(), endText, n) {
1845 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1846 addGCModeDescription(LOpts, GCEnabled);
1849 llvm::iterator_range<ranges_iterator> getRanges()
override {
1850 const CFRefBug& BugTy =
static_cast<CFRefBug&
>(getBugType());
1851 if (!BugTy.isLeak())
1853 return llvm::make_range(ranges_iterator(), ranges_iterator());
1857 class CFRefLeakReport :
public CFRefReport {
1859 const Stmt *AllocStmt;
1866 void createDescription(
CheckerContext &Ctx,
bool GCEnabled,
bool IncludeAllocationLine);
1869 CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1872 bool IncludeAllocationLine);
1875 assert(Location.isValid());
1881 void CFRefReport::addGCModeDescription(
const LangOptions &LOpts,
1883 const char *GCModeDescription =
nullptr;
1885 switch (LOpts.getGC()) {
1888 GCModeDescription =
"Code is compiled to only use garbage collection";
1893 GCModeDescription =
"Code is compiled to use reference counts";
1898 GCModeDescription =
"Code is compiled to use either garbage collection " 1899 "(GC) or reference counts (non-GC). The bug occurs " 1903 GCModeDescription =
"Code is compiled to use either garbage collection " 1904 "(GC) or reference counts (non-GC). The bug occurs " 1910 assert(GCModeDescription &&
"invalid/unknown GC mode");
1911 addExtraText(GCModeDescription);
1916 return isa<IntegerLiteral>(E) ||
1917 isa<CharacterLiteral>(E) ||
1918 isa<FloatingLiteral>(E) ||
1919 isa<ObjCBoolLiteralExpr>(E) ||
1920 isa<CXXBoolLiteralExpr>(E);
1924 if (
const auto *VR = dyn_cast_or_null<VarRegion>(MR))
1925 return std::string(VR->getDecl()->getName());
1934 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->
getDecl());
1935 if (!Method || !Method->isPropertyAccessor())
1941 std::shared_ptr<PathDiagnosticPiece>
1955 if (!CurrT)
return nullptr;
1957 const RefVal &CurrV = *CurrT;
1963 llvm::raw_string_ostream os(sbuf);
1970 if (isa<ObjCIvarRefExpr>(S) &&
1975 if (isa<ObjCArrayLiteral>(S)) {
1976 os <<
"NSArray literal is an object with a +0 retain count";
1978 else if (isa<ObjCDictionaryLiteral>(S)) {
1979 os <<
"NSDictionary literal is an object with a +0 retain count";
1981 else if (
const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1983 os <<
"NSNumber literal is an object with a +0 retain count";
1987 BoxClass = Method->getClassInterface();
1992 os << *BoxClass <<
" b";
1996 os <<
"oxed expression produces an object with a +0 retain count";
1999 else if (isa<ObjCIvarRefExpr>(S)) {
2000 os <<
"Object loaded from instance variable";
2003 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2005 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
2007 os <<
"Call to function '" << *FD <<
'\'';
2009 os <<
"function call";
2012 assert(isa<ObjCMessageExpr>(S));
2017 switch (Call->getMessageKind()) {
2031 os <<
" returns a Core Foundation object of type " 2032 << Sym->getType().getAsString() <<
" with a ";
2034 os <<
" returns an object of type " << Sym->getType().getAsString()
2039 if (!isa<ObjCObjectPointerType>(T)) {
2040 os <<
" returns an Objective-C object with a ";
2043 os <<
" returns an instance of " 2048 if (CurrV.isOwned()) {
2049 os <<
"+1 retain count";
2054 "Core Foundation objects are not automatically garbage collected.";
2058 assert (CurrV.isNotOwned());
2059 os <<
"+0 retain count";
2065 return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
2073 if (
const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
2078 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2084 AI!=AE; ++AI, ++i) {
2088 if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
2092 AEffects.push_back(Summ->getArg(i));
2096 if (
const Expr *receiver = ME->getInstanceReceiver())
2097 if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
2098 .getAsLocSymbol() == Sym) {
2100 AEffects.push_back(Summ->getReceiverEffect());
2107 RefVal PrevV = *PrevT;
2110 if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(),
Dealloc) !=
2113 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2116 if (CurrV.getKind() == RefVal::Released) {
2117 assert(CurrV.getCombinedCounts() == 0);
2118 os <<
"Object released by directly sending the '-dealloc' message";
2129 CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2134 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2136 os <<
"In GC mode a call to '" << *FD
2137 <<
"' decrements an object's retain count and registers the " 2138 "object with the garbage collector. ";
2140 if (CurrV.getKind() == RefVal::Released) {
2141 assert(CurrV.getCount() == 0);
2142 os <<
"Since it now has a 0 retain count the object can be " 2143 "automatically collected by the garbage collector.";
2146 os <<
"An object must have a 0 retain count to be garbage collected. " 2147 "After this call its retain count is +" << CurrV.getCount()
2151 os <<
"When GC is not enabled a call to '" << *FD
2152 <<
"' has no effect on its argument.";
2159 if (!PrevV.hasSameState(CurrV))
2160 switch (CurrV.getKind()) {
2162 case RefVal::NotOwned:
2163 if (PrevV.getCount() == CurrV.getCount()) {
2165 if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2168 assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2169 os <<
"Object autoreleased";
2173 if (PrevV.getCount() > CurrV.getCount())
2174 os <<
"Reference count decremented.";
2176 os <<
"Reference count incremented.";
2178 if (
unsigned Count = CurrV.getCount())
2179 os <<
" The object now has a +" << Count <<
" retain count.";
2181 if (PrevV.getKind() == RefVal::Released) {
2182 assert(GCEnabled && CurrV.getCount() > 0);
2183 os <<
" The object is not eligible for garbage collection until " 2184 "the retain count reaches 0 again.";
2189 case RefVal::Released:
2190 if (CurrV.getIvarAccessHistory() ==
2191 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
2192 CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
2193 os <<
"Strong instance variable relinquished. ";
2195 os <<
"Object released.";
2198 case RefVal::ReturnedOwned:
2200 if (CurrV.getAutoreleaseCount())
2203 os <<
"Object returned to caller as an owning reference (single " 2204 "retain count transferred to caller)";
2207 case RefVal::ReturnedNotOwned:
2208 os <<
"Object returned to caller with a +0 retain count";
2217 E=AEffects.end(); I != E; ++I) {
2224 os <<
"In GC mode an 'autorelease' has no effect.";
2227 os <<
"In GC mode the 'retain' message has no effect.";
2230 os <<
"In GC mode the 'release' message has no effect.";
2236 if (os.str().empty())
2242 auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
2247 if (
const Expr *Exp = dyn_cast_or_null<Expr>(Child))
2248 if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2249 P->addRange(Exp->getSourceRange());
2253 return std::move(P);
2262 struct AllocationInfo {
2269 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2273 static AllocationInfo
2277 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2278 const MemRegion *FirstBinding =
nullptr;
2314 if (NContext == LeakContext || NContext->
isParentOf(LeakContext))
2315 AllocationNodeInCurrentOrParentContext = N;
2319 if (!InitMethodContext)
2321 const Stmt *CE = CEP->getCallExpr();
2322 if (
const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2323 const Stmt *RecExpr = ME->getInstanceReceiver();
2325 SVal RecV = St->getSVal(RecExpr, NContext);
2327 InitMethodContext = CEP->getCalleeContext();
2338 if (InitMethodContext) {
2343 InterestingMethodContext = InitMethodContext;
2348 assert(N &&
"Could not find allocation node");
2350 FirstBinding =
nullptr;
2353 return AllocationInfo(AllocationNodeInCurrentOrParentContext,
2355 InterestingMethodContext);
2358 std::shared_ptr<PathDiagnosticPiece>
2362 return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
2365 std::shared_ptr<PathDiagnosticPiece>
2376 AllocationInfo AllocI =
2379 const MemRegion* FirstBinding = AllocI.R;
2391 llvm::raw_string_ostream os(sbuf);
2393 os <<
"Object leaked: ";
2396 if (RegionDescription) {
2397 os <<
"object allocated and stored into '" << *RegionDescription <<
'\'';
2400 os <<
"allocated object";
2406 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2412 os << (isa<ObjCMethodDecl>(D) ?
" is returned from a method " 2413 :
" is returned from a function ");
2415 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
2416 os <<
"that is annotated as CF_RETURNS_NOT_RETAINED";
2417 else if (D->
hasAttr<NSReturnsNotRetainedAttr>())
2418 os <<
"that is annotated as NS_RETURNS_NOT_RETAINED";
2422 os <<
"managed by Automatic Reference Counting";
2425 <<
"') does not start with " 2426 "'copy', 'mutableCopy', 'alloc' or 'new'." 2427 " This violates the naming convention rules" 2428 " given in the Memory Management Guide for Cocoa";
2433 os <<
"whose name ('" << *FD
2434 <<
"') does not contain 'Copy' or 'Create'. This violates the naming" 2435 " convention rules given in the Memory Management Guide for Core" 2440 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2443 <<
"' is potentially leaked when using garbage collection. Callers " 2444 "of this method do not expect a returned object with a +1 retain " 2445 "count since they expect the object to be managed by the garbage " 2449 os <<
" is not referenced later in this execution path and has a retain " 2450 "count of +" << RV->getCount();
2452 return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
2463 const Decl *PDecl = Region->getDecl();
2464 if (PDecl && isa<ParmVarDecl>(PDecl)) {
2466 Location = ParamLocation;
2467 UniqueingLocation = ParamLocation;
2486 AllocationInfo AllocI =
2489 AllocNode = AllocI.N;
2490 AllocBinding = AllocI.R;
2491 markInteresting(AllocI.InterestingMethodContext);
2500 AllocBinding =
nullptr;
2506 AllocNode->getLocationContext());
2507 Location = AllocLocation;
2511 UniqueingLocation = AllocLocation;
2512 UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2515 void CFRefLeakReport::createDescription(
CheckerContext &Ctx,
bool GCEnabled,
2516 bool IncludeAllocationLine) {
2517 assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
2518 Description.clear();
2519 llvm::raw_string_ostream os(Description);
2520 os <<
"Potential leak ";
2522 os <<
"(when using garbage collection) ";
2523 os <<
"of an object";
2526 if (RegionDescription) {
2527 os <<
" stored into '" << *RegionDescription <<
'\'';
2528 if (IncludeAllocationLine) {
2535 CFRefLeakReport::CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
2536 bool GCEnabled,
const SummaryLogTy &Log,
2539 bool IncludeAllocationLine)
2540 : CFRefReport(D, LOpts, GCEnabled, Log, n, sym,
false) {
2542 deriveAllocLocation(Ctx, sym);
2544 deriveParamLocation(Ctx, sym);
2546 createDescription(Ctx, GCEnabled, IncludeAllocationLine);
2548 addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2556 class RetainCountChecker
2557 :
public Checker< check::Bind,
2560 check::BeginFunction,
2562 check::PostStmt<BlockExpr>,
2563 check::PostStmt<CastExpr>,
2564 check::PostStmt<ObjCArrayLiteral>,
2565 check::PostStmt<ObjCDictionaryLiteral>,
2566 check::PostStmt<ObjCBoxedExpr>,
2567 check::PostStmt<ObjCIvarRefExpr>,
2569 check::PreStmt<ReturnStmt>,
2570 check::RegionChanges,
2573 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2574 mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2575 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2576 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2577 mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2579 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2582 mutable SymbolTagMap DeadSymbolTags;
2584 mutable std::unique_ptr<RetainSummaryManager> Summaries;
2585 mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2586 mutable SummaryLogTy SummaryLog;
2587 mutable bool ShouldResetSummaryLog;
2591 mutable bool IncludeAllocationLine;
2595 : ShouldResetSummaryLog(
false),
2598 ~RetainCountChecker()
override { DeleteContainerSeconds(DeadSymbolTags); }
2630 if (ShouldResetSummaryLog)
2633 ShouldResetSummaryLog = !SummaryLog.empty();
2636 CFRefBug *getLeakWithinFunctionBug(
const LangOptions &LOpts,
2637 bool GCEnabled)
const {
2639 if (!leakWithinFunctionGC)
2640 leakWithinFunctionGC.reset(
new Leak(
this,
"Leak of object when using " 2641 "garbage collection"));
2642 return leakWithinFunctionGC.get();
2644 if (!leakWithinFunction) {
2646 leakWithinFunction.reset(
new Leak(
this,
2647 "Leak of object when not using " 2648 "garbage collection (GC) in " 2649 "dual GC/non-GC code"));
2651 leakWithinFunction.reset(
new Leak(
this,
"Leak"));
2654 return leakWithinFunction.get();
2658 CFRefBug *getLeakAtReturnBug(
const LangOptions &LOpts,
bool GCEnabled)
const {
2660 if (!leakAtReturnGC)
2661 leakAtReturnGC.reset(
new Leak(
this,
2662 "Leak of returned object when using " 2663 "garbage collection"));
2664 return leakAtReturnGC.get();
2666 if (!leakAtReturn) {
2668 leakAtReturn.reset(
new Leak(
this,
2669 "Leak of returned object when not using " 2670 "garbage collection (GC) in dual " 2673 leakAtReturn.reset(
new Leak(
this,
"Leak of returned object"));
2676 return leakAtReturn.get();
2680 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx,
2681 bool GCEnabled)
const {
2687 SummariesGC.reset(
new RetainSummaryManager(Ctx,
true, ARCEnabled));
2689 assert(SummariesGC->isARCEnabled() == ARCEnabled);
2690 return *SummariesGC;
2693 Summaries.reset(
new RetainSummaryManager(Ctx,
false, ARCEnabled));
2695 assert(Summaries->isARCEnabled() == ARCEnabled);
2700 RetainSummaryManager &getSummaryManager(
CheckerContext &C)
const {
2705 const char *NL,
const char *Sep)
const override;
2719 void checkSummary(
const RetainSummary &Summ,
const CallEvent &Call,
2722 void processSummaryOfInlined(
const RetainSummary &Summ,
2729 bool Assumption)
const;
2749 RefVal V,
ArgEffect E, RefVal::Kind &hasErr,
2783 bool VisitSymbol(
SymbolRef sym)
override {
2784 state = state->remove<RefBindings>(sym);
2794 void RetainCountChecker::checkPostStmt(
const BlockExpr *BE,
2806 E = R->referenced_vars_end();
2818 for ( ; I != E; ++I) {
2819 const VarRegion *VR = I.getCapturedRegion();
2823 Regions.push_back(VR);
2827 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2828 Regions.data() + Regions.size()).getState();
2832 void RetainCountChecker::checkPostStmt(
const CastExpr *CE,
2861 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2872 const Expr *Ex)
const {
2880 state = updateSymbol(state, sym, *T,
MayEscape, hasErr, C);
2882 processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C);
2903 processObjCLiterals(C, AL);
2909 processObjCLiterals(C, DL);
2912 void RetainCountChecker::checkPostStmt(
const ObjCBoxedExpr *Ex,
2933 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2934 if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->
getOriginRegion()))
2957 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2967 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2975 State =
setRefBinding(State, Sym, PlusZero.withIvarAccess());
2979 void RetainCountChecker::checkPostCall(
const CallEvent &Call,
2981 RetainSummaryManager &Summaries = getSummaryManager(C);
2982 const RetainSummary *Summ = Summaries.getSummary(Call, C.
getState());
2985 processSummaryOfInlined(*Summ, Call, C);
2988 checkSummary(*Summ, Call, C);
3005 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
3006 PT->isObjCClassType()) {
3022 void RetainCountChecker::processSummaryOfInlined(
const RetainSummary &Summ,
3028 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3039 if (MsgInvocation) {
3061 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.
getAsRegion());
3065 QualType PointeeTy = ArgRegion->getValueType();
3069 SVal PointeeVal = State->getSVal(ArgRegion);
3086 llvm_unreachable(
"only for out parameters");
3092 void RetainCountChecker::checkSummary(
const RetainSummary &Summ,
3102 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3110 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3121 bool ReceiverIsTracked =
false;
3124 if (MsgInvocation) {
3127 ReceiverIsTracked =
true;
3128 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3141 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3149 if (ReceiverIsTracked)
3150 RE = getSummaryManager(C).getObjAllocRetEffect();
3157 llvm_unreachable(
"Unhandled RetEffect.");
3208 if (ShouldResetSummaryLog) {
3210 ShouldResetSummaryLog =
false;
3212 SummaryLog[NewNode] = &Summ;
3218 RefVal V,
ArgEffect E, RefVal::Kind &hasErr,
3223 if (!IgnoreRetainMsg)
3245 V = V ^ RefVal::ErrorUseAfterRelease;
3246 hasErr = V.getKind();
3255 llvm_unreachable(
"DecRefMsg/IncRefMsg/MakeCollectable already converted");
3259 llvm_unreachable(
"Applies to pointer-to-pointer parameters, which should " 3260 "not have ref state.");
3265 V = V ^ RefVal::ErrorDeallocGC;
3266 hasErr = V.getKind();
3270 switch (V.getKind()) {
3272 llvm_unreachable(
"Invalid RefVal state for an explicit dealloc.");
3275 V = V ^ RefVal::Released;
3278 case RefVal::NotOwned:
3279 V = V ^ RefVal::ErrorDeallocNotOwned;
3280 hasErr = V.getKind();
3286 if (V.getKind() == RefVal::Owned) {
3287 V = V ^ RefVal::NotOwned;
3300 V = V.autorelease();
3308 switch (V.getKind()) {
3310 llvm_unreachable(
"Invalid RefVal state for a retain.");
3312 case RefVal::NotOwned:
3315 case RefVal::Released:
3318 V = (V ^ RefVal::Owned) + 1;
3326 switch (V.getKind()) {
3329 llvm_unreachable(
"Invalid RefVal state for a release.");
3332 assert(V.getCount() > 0);
3333 if (V.getCount() == 1) {
3335 V.getIvarAccessHistory() ==
3336 RefVal::IvarAccessHistory::AccessedDirectly)
3337 V = V ^ RefVal::NotOwned;
3339 V = V ^ RefVal::Released;
3347 case RefVal::NotOwned:
3348 if (V.getCount() > 0) {
3352 }
else if (V.getIvarAccessHistory() ==
3353 RefVal::IvarAccessHistory::AccessedDirectly) {
3358 V = V.releaseViaIvar() ^ RefVal::Released;
3360 V = V ^ RefVal::ErrorReleaseNotOwned;
3361 hasErr = V.getKind();
3365 case RefVal::Released:
3368 V = V ^ RefVal::ErrorUseAfterRelease;
3369 hasErr = V.getKind();
3389 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3399 llvm_unreachable(
"Unhandled error.");
3400 case RefVal::ErrorUseAfterRelease:
3401 if (!useAfterRelease)
3402 useAfterRelease.reset(
new UseAfterRelease(
this));
3403 BT = useAfterRelease.get();
3405 case RefVal::ErrorReleaseNotOwned:
3406 if (!releaseNotOwned)
3407 releaseNotOwned.reset(
new BadRelease(
this));
3408 BT = releaseNotOwned.get();
3410 case RefVal::ErrorDeallocGC:
3412 deallocGC.reset(
new DeallocGC(
this));
3413 BT = deallocGC.get();
3415 case RefVal::ErrorDeallocNotOwned:
3416 if (!deallocNotOwned)
3417 deallocNotOwned.reset(
new DeallocNotOwned(
this));
3418 BT = deallocNotOwned.get();
3423 auto report = std::unique_ptr<BugReport>(
3425 SummaryLog, N, Sym));
3426 report->addRange(ErrorRange);
3453 StringRef FName = II->
getName();
3454 FName = FName.substr(FName.find_first_not_of(
'_'));
3457 bool canEval =
false;
3460 bool hasTrustedImplementationAnnotation =
false;
3465 canEval = II->
isStr(
"NSMakeCollectable");
3479 hasTrustedImplementationAnnotation = canEval;
3489 SVal RetVal = state->getSVal(CE->
getArg(0), LCtx);
3491 (hasTrustedImplementationAnnotation && !ResultTy.
isNull())) {
3498 state = state->BindExpr(CE, LCtx, RetVal,
false);
3505 const RefVal *Binding =
nullptr;
3510 state = state->invalidateRegions(
3512 hasTrustedImplementationAnnotation);
3527 void RetainCountChecker::checkPreStmt(
const ReturnStmt *S,
3556 switch (X.getKind()) {
3557 case RefVal::Owned: {
3558 unsigned cnt = X.getCount();
3560 X.setCount(cnt - 1);
3561 X = X ^ RefVal::ReturnedOwned;
3565 case RefVal::NotOwned: {
3566 unsigned cnt = X.getCount();
3568 X.setCount(cnt - 1);
3569 X = X ^ RefVal::ReturnedOwned;
3572 X = X ^ RefVal::ReturnedNotOwned;
3595 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3607 RetainSummaryManager &Summaries = getSummaryManager(C);
3613 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3614 RE = Summ->getRetEffect();
3615 }
else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3616 if (!isa<CXXMethodDecl>(FD)) {
3617 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3618 RE = Summ->getRetEffect();
3622 checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3625 void RetainCountChecker::checkReturnWithRetEffect(
const ReturnStmt *S,
3637 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3641 if (X.isReturnedOwned() && X.getCount() == 0) {
3643 bool hasError =
false;
3650 X = X ^ RefVal::ErrorGCLeakReturned;
3657 X = X ^ RefVal::ErrorLeakReturned;
3669 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefLeakReport(
3670 *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3671 SummaryLog, N, Sym, C, IncludeAllocationLine)));
3675 }
else if (X.isReturnedNotOwned()) {
3677 if (X.getIvarAccessHistory() ==
3678 RefVal::IvarAccessHistory::AccessedDirectly) {
3682 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3686 state =
setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3689 ReturnNotOwnedTag(
this,
"ReturnNotOwnedForOwned");
3693 if (!returnNotOwnedForOwned)
3694 returnNotOwnedForOwned.reset(
new ReturnedNotOwnedForOwned(
this));
3696 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefReport(
3709 void RetainCountChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
3712 bool escapes =
true;
3723 escapes = !regionLoc->getRegion()->hasStackStorage();
3731 SVal StoredVal = state->getSVal(regionLoc->getRegion());
3732 if (StoredVal != val)
3739 escapes = !isa<VarRegion>(regionLoc->getRegion());
3747 const VarDecl *VD = LVR->getDecl();
3748 if (VD->
hasAttr<CleanupAttr>()) {
3761 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3767 bool Assumption)
const {
3774 RefBindingsTy B = state->get<RefBindings>();
3779 bool changed =
false;
3782 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3788 B = RefBFactory.remove(B, I.getKey());
3793 state = state->set<RefBindings>(B);
3808 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3810 E = ExplicitRegions.end(); I != E; ++I) {
3812 WhitelistedSymbols.insert(SR->getSymbol());
3815 for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3816 E = invalidated->end(); I!=E; ++I) {
3818 if (WhitelistedSymbols.count(sym))
3836 unsigned ACnt = V.getAutoreleaseCount();
3843 unsigned Cnt = V.getCount();
3847 if (V.getKind() == RefVal::ReturnedOwned)
3853 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
3854 V = V.releaseViaIvar();
3861 if (V.getKind() == RefVal::ReturnedOwned)
3862 V = V ^ RefVal::ReturnedNotOwned;
3864 V = V ^ RefVal::NotOwned;
3866 V.setCount(V.getCount() - ACnt);
3867 V.setAutoreleaseCount(0);
3878 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3883 V = V ^ RefVal::ErrorOverAutorelease;
3889 llvm::raw_svector_ostream os(sbuf);
3890 os <<
"Object was autoreleased ";
3891 if (V.getAutoreleaseCount() > 1)
3892 os << V.getAutoreleaseCount() <<
" times but the object ";
3895 os <<
"has a +" << V.getCount() <<
" retain count";
3897 if (!overAutorelease)
3898 overAutorelease.reset(
new OverAutorelease(
this));
3902 new CFRefReport(*overAutorelease, LOpts,
false,
3903 SummaryLog, N, Sym, os.str())));
3921 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3923 else if (V.isOwned())
3925 else if (V.isNotOwned() || V.isReturnedOwned())
3926 hasLeak = (V.getCount() > 0);
3933 Leaked.push_back(sid);
3947 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3951 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3952 : getLeakAtReturnBug(LOpts, GCEnabled);
3953 assert(BT &&
"BugType not initialized.");
3956 new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
3957 IncludeAllocationLine)));
3964 void RetainCountChecker::checkBeginFunction(
CheckerContext &Ctx)
const {
3976 const RetainSummary *FunctionSummary = getSummaryManager(Ctx).getFunctionSummary(FD);
3977 ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
3979 for (
unsigned idx = 0, e = FD->
getNumParams(); idx != e; ++idx) {
3981 SymbolRef Sym = state->getSVal(state->getRegion(Param, LCtx)).getAsSymbol();
3984 const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
3986 state =
setRefBinding(state, Sym, RefVal::makeOwned(RetEffect::ObjKind::Generalized, Ty));
3988 state =
setRefBinding(state, Sym, RefVal::makeNotOwned(RetEffect::ObjKind::Generalized, Ty));
3994 void RetainCountChecker::checkEndFunction(
const ReturnStmt *RS,
3997 RefBindingsTy B = state->get<RefBindings>();
4007 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
4008 state = handleAutoreleaseCounts(state, Pred,
nullptr, Ctx,
4009 I->first, I->second);
4021 B = state->get<RefBindings>();
4024 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
4025 state = handleSymbolDeath(state, I->first, I->second, Leaked);
4027 processLeaks(state, Leaked, Ctx, Pred);
4031 RetainCountChecker::getDeadSymbolTag(
SymbolRef sym)
const {
4035 llvm::raw_svector_ostream out(buf);
4036 out <<
"Dead Symbol : ";
4043 void RetainCountChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
4048 RefBindingsTy B = state->get<RefBindings>();
4053 E = SymReaper.
dead_end(); I != E; ++I) {
4055 if (
const RefVal *T = B.lookup(Sym)){
4059 state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
4065 state = handleSymbolDeath(state, *I, *
getRefBinding(state, Sym), Leaked);
4069 if (Leaked.empty()) {
4074 Pred = processLeaks(state, Leaked, C, Pred);
4083 B = state->get<RefBindings>();
4088 B = F.remove(B, *I);
4090 state = state->set<RefBindings>(B);
4094 void RetainCountChecker::printState(raw_ostream &Out,
ProgramStateRef State,
4095 const char *NL,
const char *Sep)
const {
4097 RefBindingsTy B = State->get<RefBindings>();
4104 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
4105 Out << I->first <<
" : ";
4106 I->second.print(Out);
4125 namespace objc_retain {
4130 #define createCallEffect(D, KIND)\ 4131 ASTContext &Ctx = D->getASTContext();\ 4132 LangOptions L = Ctx.getLangOpts();\ 4133 RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\ 4134 const RetainSummary *S = M.get ## KIND ## Summary(D);\ 4135 CallEffects CE(S->getRetEffect());\ 4136 CE.Receiver = S->getReceiverEffect();\ 4137 unsigned N = D->param_size();\ 4138 for (unsigned i = 0; i < N; ++i) {\ 4139 CE.Args.push_back(S->getArg(i));\ 4152 #undef createCallEffect const ExplodedNode * getOriginalNode(const ExplodedNode *N) override
const BlockDecl * getBlockDecl() const
FunctionDecl * getDefinition()
Get the definition for this declaration.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
Represents a function declaration or definition.
Smart pointer class that efficiently represents Objective-C method names.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T -> getSizeExpr()))
A (possibly-)qualified type.
MemRegion - The root abstract class for all memory regions.
ExplodedNode * generateErrorNode(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a transition to a node that will be used to report an error.
static RetEffect MakeOwnedWhenTrackedReceiver()
ASTContext & getASTContext()
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
ObjCInterfaceDecl * getClassInterface()
bool operator==(CanQual< T > x, CanQual< U > y)
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Stmt - This represents one statement.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
FunctionType - C99 6.7.5.3 - Function Declarators.
Bridging via __bridge, which does nothing but reinterpret the bits.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym)
Defines the SourceManager interface.
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph).
Decl - This represents one declaration (or definition), e.g.
Represents a point when we begin processing an inlined call.
Manages the lifetime of CallEvent objects.
The argument has its reference count decreased by 1.
Indicates that the tracked object is an Objective-C object.
bool isCocoaObjectRef(QualType T)
llvm::DenseMap< Stmt *, Stmt * > MapTy
Indicates that the tracked object is a generalized object.
const ProgramStateRef & getState() const
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
param_const_iterator param_end() const
static RetEffect MakeNoRet()
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
bool isConsumedExpr(Expr *E) const
Represents a variable declaration or definition.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
QualType getReturnType() const
unsigned getNumParams() const
const T * getAs() const
Member-template getAs<specific type>'.
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
const Decl & getCodeDecl() const
ObjCMethodDecl - Represents an instance or class method declaration.
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
virtual const MemRegion * getOriginRegion() const
Find the region from which this symbol originates.
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
Represents a parameter to a function.
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
const char *const MemoryCoreFoundationObjectiveC
bool isParentOf(const LocationContext *LC) const
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
const MemRegion * getSuperRegion() const
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
Convenience method to query the state to see if a symbol is null or not null, or if neither assumptio...
One of these records is kept for each identifier that is lexed.
static RetEffect MakeNoRetHard()
MemRegionManager & getRegionManager()
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *... IIs)
const ParmVarDecl *const * param_const_iterator
bool isObjCIdType() const
The argument is treated as if an -autorelease message had been sent to the referenced object...
unsigned getSpellingLineNumber(bool *Invalid=nullptr) const
const Expr * getRetValue() const
const MemRegion * getRegion()
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
ObjCArrayLiteral - used for objective-c array containers; as in: @["Hello", NSApp, [NSNumber numberWithInt:42]];.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
static ObjCSummaryKey getTombstoneKey()
static bool isRetain(const FunctionDecl *FD, StringRef FName)
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)
virtual llvm::iterator_range< ranges_iterator > getRanges()
Get the SourceRanges associated with the report.
static bool isEqual(const ObjCSummaryKey &LHS, const ObjCSummaryKey &RHS)
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
bool followsCreateRule(const FunctionDecl *FD)
Represents any expression that calls an Objective-C method.
virtual Kind getKind() const =0
Returns the kind of call this is.
bool hasNonZeroCallbackArg() const
Returns true if any of the arguments appear to represent callbacks.
static void Profile(const ArgEffect X, FoldingSetNodeID &ID)
ProgramStateManager & getStateManager()
The argument has its reference count increased by 1.
virtual void dumpToStream(raw_ostream &os) const
const LocationContext * getLocationContext() const
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
const LocationContext * getParent() const
SVal getReturnValue() const
Returns the return value of the call.
static PathDiagnosticLocation create(const Decl *D, const SourceManager &SM)
Create a location corresponding to the given declaration.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Represents an ObjC class declaration.
Bridging via __bridge_transfer, which transfers ownership of an Objective-C pointer into ARC...
static bool isNumericLiteralExpression(const Expr *E)
QualType getReturnType() const
virtual QualType getType() const =0
param_iterator param_begin()
NodeMapClosure & getNodeResolver()
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
Const iterator for iterating over Stmt * arrays that contain only Expr *.
Indicates that the returned value is an owned (+1) symbol.
Represents a prototype with parameter type info, e.g.
const Stmt * getCallSite() const
Indicates that the return value is an owned object when the receiver is also a tracked object...
static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation)
Returns true if the declaration 'D' is annotated with 'rcAnnotation'.
The argument is treated as potentially escaping, meaning that even when its reference count hits 0 it...
llvm::ImmutableMap< unsigned, ArgEffect > ArgEffects
ArgEffects summarizes the effects of a function/method call on all of its arguments.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const RegionTy * getAs() const
SymbolicRegion - A special, "non-concrete" region.
ObjKind getObjKind() const
Expr - This represents one expression.
Defines the clang::LangOptions interface.
Indicates that the tracked object is a CF object.
Indicates that the object is not owned and controlled by the Garbage collector.
bool isObjCRetainableType() const
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts)
Returns true if leak diagnostics should directly reference the allocatin site (where possible)...
static CallEffects getEffect(const ObjCMethodDecl *MD)
Return the CallEfect for a given Objective-C method.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
ObjCInterfaceDecl * getSuperClass() const
static bool isRelease(const FunctionDecl *FD, StringRef FName)
ObjKind
Determines the object kind of a tracked object.
static bool isAutorelease(const FunctionDecl *FD, StringRef FName)
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
bool isCFObjectRef(QualType T)
An expression that sends a message to the given Objective-C object or class.
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
bool isInstanceMethod() const
unsigned getNumArgs() const
static RetEffect MakeGCNotOwned()
void markInteresting(SymbolRef sym)
Selector getSelector() const
ObjCBridgeCastKind getBridgeKind() const
Determine which kind of bridge is being performed via this cast.
CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx)
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Represents a C function or static C++ member function call.
static StringRef getIdentifier(const Token &Tok)
static bool isSynthesizedAccessor(const StackFrameContext *SFC)
Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
const VarDecl * getDecl() const
CHECKER * registerChecker(AT... Args)
Used to register checkers.
static RetEffect MakeNotOwned(ObjKind o)
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
BugReporter is a utility class for generating PathDiagnostics for analysis.
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
const MemRegion * StripCasts(bool StripBaseCasts=true) const
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
std::string getAsString() const
Derive the full selector name (e.g.
The argument has its reference count increased by 1.
ObjCMethodFamily getMethodFamily() const
Derive the conventional family of this method.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
QualType getReturnType() const
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static ObjCSummaryKey getEmptyKey()
ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)
Generate a sink node.
The argument has its reference count decreased by 1 to model a transferred bridge cast under ARC...
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
const MemRegion * getAsRegion() const
static ProgramStateRef updateOutParameter(ProgramStateRef State, SVal ArgVal, ArgEffect Effect)
static const RefVal * getRefBinding(ProgramStateRef State, SymbolRef Sym)
static void Profile(const RetEffect &X, FoldingSetNodeID &ID)
static Optional< std::string > describeRegion(const MemRegion *MR)
const ParmVarDecl * getParamDecl(unsigned i) const
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
static bool isGeneralizedObjectRef(QualType Ty)
const StackFrameContext * getStackFrame() const
A class responsible for cleaning up unused symbols.
SVal getSVal(const Stmt *S) const
Get the value of an arbitrary expression at this node.
ObjCBoxedExpr - used for generalized expression boxing.
const ObjCMethodDecl * getDecl() const override
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
StringRef getName() const
Return the actual identifier string.
virtual const ObjCMessageExpr * getOriginExpr() const
SymbolSetTy::const_iterator dead_iterator
An Objective-C "bridged" cast expression, which casts between Objective-C pointers and C pointers...
Selector getSelector() const
static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val)
All typestate tracking of the object ceases.
Dataflow Directional Tag Classes.
bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())
ASTContext & getASTContext()
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
The argument is treated as if an -dealloc message had been sent to the referenced object...
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and LocationC...
Performs the combined functionality of DecRef and StopTrackingHard.
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
bool isKeywordSelector() const
static bool isTrustedReferenceCountImplementation(const FunctionDecl *FD)
Returns true if the function declaration 'FD' contains 'rc_ownership_trusted_implementation' annotate...
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Represents an abstract call to a function or method along a particular path.
Bridging via __bridge_retain, which makes an ARC object available as a +1 C pointer.
AnalyzerOptions & getAnalyzerOptions()
RetEffect summarizes a call's retain/release behavior with respect to its return value.
const Decl * getDecl() const
dead_iterator dead_begin() const
param_iterator param_end()
static ArgEffect getStopTrackingHardEquivalent(ArgEffect E)
SourceRange getReceiverRange() const
Source range of the receiver.
Represents a pointer to an Objective C object.
bool isInstanceMessage() const
const StackFrameContext * getStackFrame() const
const FunctionDecl * getAsFunctionDecl() const
getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a CodeTextRegion wrapping a FunctionDecl...
#define createCallEffect(D, KIND)
const ProgramStateRef & getState() const
Performs the combined functionality of DecRefMsg and StopTrackingHard.
ProgramStateManager & getStateManager()
param_const_iterator param_begin() const
const StackFrameContext * getStackFrame() const
dead_iterator dead_end() const
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +0 v...
static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName)
ObjCIvarRefExpr - A reference to an ObjC instance variable.
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
QualType getResultType() const
Returns the result type, adjusted for references.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
No particular method family.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
Indicates that no retain count information is tracked for the return value.
Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
pred_iterator pred_begin()
SourceManager & getSourceManager()
virtual unsigned getNumArgs() const =0
Returns the number of arguments (explicit and implicit).
static PathDiagnosticLocation createEndOfPath(const ExplodedNode *N, const SourceManager &SM)
Create a location corresponding to the next valid ExplodedNode as end of path location.
static RetEffect MakeOwned(ObjKind o)
const MemRegion * getBaseRegion() const
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A SourceLocation and its associated SourceManager.
static Decl::Kind getKind(const Decl *D)
bool isPointerType() const
All typestate tracking of the object ceases.
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
static llvm::ImmutableListFactory< const FieldRegion * > Factory
The argument has its reference count decreased by 1.
Encapsulates the retain count semantics on the arguments, return value, and receiver (if any) of a fu...
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
This class provides an interface through which checkers can create individual bug reports...
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
static unsigned getHashValue(const ObjCSummaryKey &V)
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
AnalysisDeclContext * getAnalysisDeclContext() const
const LocationContext * getLocationContext() const
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
Indicates that the returned value is an object with retain count semantics but that it is not owned (...
const LangOptions & getLangOpts() const
This class handles loading and caching of source files into memory.
SourceManager & getSourceManager()
static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx)
GetReturnType - Used to get the return type of a message expression or function call with the intenti...
bool isObjCGCEnabled() const
QualType getPointeeType() const
Gets the type pointed to by this ObjC pointer.