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"
43 using namespace clang;
45 using namespace objc_retain;
46 using llvm::StrInStrNoCase;
55 ID.AddInteger((
unsigned) X);
60 ID.AddInteger((
unsigned) X.
getKind());
101 enum class IvarAccessHistory {
104 ReleasedAfterDirectAccess
118 unsigned RawKind : 5;
123 unsigned RawObjectKind : 2;
134 unsigned RawIvarAccessHistory : 2;
137 IvarAccessHistory IvarAccess)
138 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
139 RawObjectKind(static_cast<unsigned>(o)),
140 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
141 assert(
getKind() == k &&
"not enough bits for the kind");
142 assert(getObjKind() == o &&
"not enough bits for the object kind");
143 assert(getIvarAccessHistory() == IvarAccess &&
"not enough bits");
153 unsigned getCount()
const {
return Cnt; }
154 unsigned getAutoreleaseCount()
const {
return ACnt; }
155 unsigned getCombinedCounts()
const {
return Cnt + ACnt; }
160 void setCount(
unsigned i) {
163 void setAutoreleaseCount(
unsigned i) {
167 QualType getType()
const {
return T; }
174 IvarAccessHistory getIvarAccessHistory()
const {
175 return static_cast<IvarAccessHistory
>(RawIvarAccessHistory);
178 bool isOwned()
const {
182 bool isNotOwned()
const {
186 bool isReturnedOwned()
const {
187 return getKind() == ReturnedOwned;
190 bool isReturnedNotOwned()
const {
191 return getKind() == ReturnedNotOwned;
199 unsigned Count = 1) {
208 unsigned Count = 0) {
212 RefVal operator-(
size_t i)
const {
213 return RefVal(
getKind(), getObjKind(), getCount() - i,
214 getAutoreleaseCount(), getType(), getIvarAccessHistory());
217 RefVal operator+(
size_t i)
const {
218 return RefVal(
getKind(), getObjKind(), getCount() + i,
219 getAutoreleaseCount(), getType(), getIvarAccessHistory());
222 RefVal operator^(
Kind k)
const {
223 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
224 getType(), getIvarAccessHistory());
227 RefVal autorelease()
const {
228 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
229 getType(), getIvarAccessHistory());
232 RefVal withIvarAccess()
const {
234 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
235 getType(), IvarAccessHistory::AccessedDirectly);
237 RefVal releaseViaIvar()
const {
238 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
239 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
240 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
245 bool hasSameState(
const RefVal &
X)
const {
246 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
247 getIvarAccessHistory() == X.getIvarAccessHistory();
251 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
254 void Profile(llvm::FoldingSetNodeID&
ID)
const {
256 ID.AddInteger(RawKind);
259 ID.AddInteger(RawObjectKind);
260 ID.AddInteger(RawIvarAccessHistory);
263 void print(raw_ostream &Out)
const;
266 void RefVal::print(raw_ostream &Out)
const {
268 Out <<
"Tracked " << T.getAsString() <<
'/';
271 default: llvm_unreachable(
"Invalid RefVal kind");
274 unsigned cnt = getCount();
275 if (cnt) Out <<
" (+ " << cnt <<
")";
281 unsigned cnt = getCount();
282 if (cnt) Out <<
" (+ " << cnt <<
")";
286 case ReturnedOwned: {
287 Out <<
"ReturnedOwned";
288 unsigned cnt = getCount();
289 if (cnt) Out <<
" (+ " << cnt <<
")";
293 case ReturnedNotOwned: {
294 Out <<
"ReturnedNotOwned";
295 unsigned cnt = getCount();
296 if (cnt) Out <<
" (+ " << cnt <<
")";
305 Out <<
"-dealloc (GC)";
308 case ErrorDeallocNotOwned:
309 Out <<
"-dealloc (not-owned)";
316 case ErrorLeakReturned:
317 Out <<
"Leaked (Bad naming)";
320 case ErrorGCLeakReturned:
321 Out <<
"Leaked (GC-ed at return)";
324 case ErrorUseAfterRelease:
325 Out <<
"Use-After-Release [ERROR]";
328 case ErrorReleaseNotOwned:
329 Out <<
"Release of Not-Owned [ERROR]";
332 case RefVal::ErrorOverAutorelease:
333 Out <<
"Over-autoreleased";
336 case RefVal::ErrorReturnedNotOwned:
337 Out <<
"Non-owned object returned instead of owned";
341 switch (getIvarAccessHistory()) {
344 case IvarAccessHistory::AccessedDirectly:
345 Out <<
" [direct ivar access]";
347 case IvarAccessHistory::ReleasedAfterDirectAccess:
348 Out <<
" [released after direct ivar access]";
352 Out <<
" [autorelease -" << ACnt <<
']';
365 return State->get<RefBindings>(Sym);
370 return State->set<RefBindings>(Sym, Val);
374 return State->remove<RefBindings>(Sym);
382 class RetainSummary {
403 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
408 if (
const ArgEffect *AE = Args.lookup(idx))
411 return DefaultArgEffect;
414 void addArg(ArgEffects::Factory &af,
unsigned idx,
ArgEffect e) {
415 Args = af.add(Args, idx, e);
420 DefaultArgEffect = E;
424 RetEffect getRetEffect()
const {
return Ret; }
427 void setRetEffect(
RetEffect E) { Ret = E; }
431 void setReceiverEffect(
ArgEffect e) { Receiver = e; }
435 ArgEffect getReceiverEffect()
const {
return Receiver; }
440 bool operator==(
const RetainSummary &Other)
const {
441 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
442 Receiver == Other.Receiver && Ret == Other.Ret;
446 void Profile(llvm::FoldingSetNodeID&
ID)
const {
448 ID.Add(DefaultArgEffect);
454 bool isSimple()
const {
455 return Args.isEmpty();
459 ArgEffects getArgEffects()
const {
return Args; }
460 ArgEffect getDefaultArgEffect()
const {
return DefaultArgEffect; }
462 friend class RetainSummaryManager;
471 class ObjCSummaryKey {
479 : II(d ? d->getIdentifier() : nullptr),
S(s) {}
482 : II(nullptr),
S(s) {}
485 Selector getSelector()
const {
return S; }
502 typedef std::pair<IdentifierInfo*, Selector> PairTy;
507 static bool isEqual(
const ObjCSummaryKey& LHS,
const ObjCSummaryKey& RHS) {
508 return LHS.getIdentifier() == RHS.getIdentifier() &&
509 LHS.getSelector() == RHS.getSelector();
516 class ObjCSummaryCache {
517 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *>
MapTy;
520 ObjCSummaryCache() {}
525 ObjCSummaryKey K(D, S);
526 MapTy::iterator I = M.find(K);
540 if ((I = M.find(ObjCSummaryKey(
C, S))) != M.end())
549 const RetainSummary *Summ = I->second;
557 MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
560 I = M.find(ObjCSummaryKey(S));
562 return I == M.end() ?
nullptr : I->second;
565 const RetainSummary *& operator[](ObjCSummaryKey K) {
569 const RetainSummary *& operator[](
Selector S) {
570 return M[ ObjCSummaryKey(S) ];
580 class RetainSummaryManager {
586 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
589 typedef ObjCSummaryCache ObjCMethodSummariesTy;
591 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
601 const bool GCEnabled;
604 const bool ARCEnabled;
607 FuncSummariesTy FuncSummaries;
611 ObjCMethodSummariesTy ObjCClassMethodSummaries;
614 ObjCMethodSummariesTy ObjCMethodSummaries;
618 llvm::BumpPtrAllocator BPAlloc;
621 ArgEffects::Factory AF;
636 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
646 enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
648 const RetainSummary *getUnarySummary(
const FunctionType* FT,
651 const RetainSummary *getCFSummaryCreateRule(
const FunctionDecl *FD);
652 const RetainSummary *getCFSummaryGetRule(
const FunctionDecl *FD);
653 const RetainSummary *getCFCreateGetRuleSummary(
const FunctionDecl *FD);
655 const RetainSummary *getPersistentSummary(
const RetainSummary &OldSumm);
657 const RetainSummary *getPersistentSummary(
RetEffect RetEff,
660 RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
661 return getPersistentSummary(Summ);
664 const RetainSummary *getDoNothingSummary() {
668 const RetainSummary *getDefaultSummary() {
673 const RetainSummary *getPersistentStopSummary() {
678 void InitializeClassMethodSummaries();
679 void InitializeMethodSummaries();
681 void addNSObjectClsMethSummary(
Selector S,
const RetainSummary *Summ) {
682 ObjCClassMethodSummaries[
S] = Summ;
685 void addNSObjectMethSummary(
Selector S,
const RetainSummary *Summ) {
686 ObjCMethodSummaries[
S] = Summ;
689 void addClassMethSummary(
const char* Cls,
const char* name,
690 const RetainSummary *Summ,
bool isNullary =
true) {
694 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
697 void addInstMethSummary(
const char* Cls,
const char* nullaryName,
698 const RetainSummary *Summ) {
701 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
704 void addMethodSummary(
IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
705 const RetainSummary *Summ,
va_list argp) {
707 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
710 void addInstMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
713 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
717 void addClsMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
720 addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
724 void addClsMethSummary(
IdentifierInfo *II,
const RetainSummary * Summ, ...) {
727 addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
733 RetainSummaryManager(
ASTContext &ctx,
bool gcenabled,
bool usesARC)
735 GCEnabled(gcenabled),
737 AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
738 ObjCAllocRetE(gcenabled
742 ObjCInitRetE(gcenabled
745 :
RetEffect::MakeOwnedWhenTrackedReceiver())) {
746 InitializeClassMethodSummaries();
747 InitializeMethodSummaries();
750 const RetainSummary *getSummary(
const CallEvent &Call,
753 const RetainSummary *getFunctionSummary(
const FunctionDecl *FD);
758 ObjCMethodSummariesTy &CachedSummaries);
760 const RetainSummary *getInstanceMethodSummary(
const ObjCMethodCall &M,
763 const RetainSummary *getClassMethodSummary(
const ObjCMethodCall &M) {
768 M.getResultType(), ObjCClassMethodSummaries);
778 ObjCMethodSummariesTy *CachedSummaries;
780 CachedSummaries = &ObjCMethodSummaries;
782 CachedSummaries = &ObjCClassMethodSummaries;
784 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
787 const RetainSummary *getStandardMethodSummary(
const ObjCMethodDecl *MD,
794 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
797 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
800 void updateSummaryForCall(
const RetainSummary *&Summ,
803 bool isGCEnabled()
const {
return GCEnabled; }
805 bool isARCEnabled()
const {
return ARCEnabled; }
807 bool isARCorGCEnabled()
const {
return GCEnabled || ARCEnabled; }
809 RetEffect getObjAllocRetEffect()
const {
return ObjCAllocRetE; }
811 friend class RetainSummaryTemplate;
818 class RetainSummaryTemplate {
819 RetainSummaryManager &Manager;
820 const RetainSummary *&RealSummary;
821 RetainSummary ScratchSummary;
824 RetainSummaryTemplate(
const RetainSummary *&real, RetainSummaryManager &mgr)
825 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(
false) {}
827 ~RetainSummaryTemplate() {
829 RealSummary = Manager.getPersistentSummary(ScratchSummary);
834 return ScratchSummary;
837 RetainSummary *operator->() {
839 return &ScratchSummary;
849 ArgEffects RetainSummaryManager::getArgEffects() {
851 ScratchArgs = AF.getEmptyMap();
855 const RetainSummary *
856 RetainSummaryManager::getPersistentSummary(
const RetainSummary &OldSumm) {
858 if (OldSumm.isSimple()) {
859 llvm::FoldingSetNodeID
ID;
863 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
866 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
867 new (N) CachedSummaryNode(OldSumm);
868 SimpleSummaries.InsertNode(N, Pos);
871 return &N->getValue();
874 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
875 new (Summ) RetainSummary(OldSumm);
884 return FName.endswith(
"Retain");
888 return FName.endswith(
"Release");
892 return FName.endswith(
"Autorelease");
898 return FName.find(
"MakeCollectable") != StringRef::npos;
925 llvm_unreachable(
"Unknown ArgEffect kind");
928 void RetainSummaryManager::updateSummaryForCall(
const RetainSummary *&S,
936 ArgEffects CustomArgEffects = S->getArgEffects();
937 for (ArgEffects::iterator I = CustomArgEffects.begin(),
938 E = CustomArgEffects.end();
941 if (Translated != DefEffect)
942 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
954 if (Name->isStr(
"CGBitmapContextCreateWithData"))
955 RE = S->getRetEffect();
959 S = getPersistentSummary(RE, RecEffect, DefEffect);
975 if (MC->getMethodFamily() ==
OMF_init && MC->isReceiverSelfOrSuper()) {
979 const Expr *ME = MC->getOriginExpr();
983 RetainSummaryTemplate ModifiableSummaryTemplate(S, *
this);
984 ModifiableSummaryTemplate->setReceiverEffect(
DoNothing);
992 const RetainSummary *
993 RetainSummaryManager::getSummary(
const CallEvent &Call,
995 const RetainSummary *Summ;
998 Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
1007 return getPersistentStopSummary();
1011 Summ = getInstanceMethodSummary(Msg, State);
1013 Summ = getClassMethodSummary(Msg);
1018 updateSummaryForCall(Summ, Call);
1020 assert(Summ &&
"Unknown call type?");
1024 const RetainSummary *
1025 RetainSummaryManager::getFunctionSummary(
const FunctionDecl *FD) {
1028 return getDefaultSummary();
1031 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
1032 if (I != FuncSummaries.end())
1036 const RetainSummary *S =
nullptr;
1037 bool AllowAnnotations =
true;
1042 S = getPersistentStopSummary();
1053 StringRef FName = II->
getName();
1057 FName = FName.substr(FName.find_first_not_of(
'_'));
1064 assert(ScratchArgs.isEmpty());
1066 if (FName ==
"pthread_create" || FName ==
"pthread_setspecific") {
1069 S = getPersistentStopSummary();
1070 }
else if (FName ==
"NSMakeCollectable") {
1073 ? getUnarySummary(FT, cfmakecollectable)
1074 : getPersistentStopSummary();
1077 AllowAnnotations =
false;
1078 }
else if (FName ==
"CFPlugInInstanceCreate") {
1080 }
else if (FName ==
"IOBSDNameMatching" ||
1081 FName ==
"IOServiceMatching" ||
1082 FName ==
"IOServiceNameMatching" ||
1083 FName ==
"IORegistryEntrySearchCFProperty" ||
1084 FName ==
"IORegistryEntryIDMatching" ||
1085 FName ==
"IOOpenFirmwarePathMatching") {
1090 }
else if (FName ==
"IOServiceGetMatchingService" ||
1091 FName ==
"IOServiceGetMatchingServices") {
1095 ScratchArgs = AF.add(ScratchArgs, 1,
DecRef);
1097 }
else if (FName ==
"IOServiceAddNotification" ||
1098 FName ==
"IOServiceAddMatchingNotification") {
1101 ScratchArgs = AF.add(ScratchArgs, 2,
DecRef);
1103 }
else if (FName ==
"CVPixelBufferCreateWithBytes") {
1112 }
else if (FName ==
"CGBitmapContextCreateWithData") {
1120 }
else if (FName ==
"CVPixelBufferCreateWithPlanarBytes") {
1128 }
else if (FName ==
"dispatch_set_context" ||
1129 FName ==
"xpc_connection_set_context") {
1138 }
else if (FName.startswith(
"NSLog")) {
1139 S = getDoNothingSummary();
1140 }
else if (FName.startswith(
"NS") &&
1141 (FName.find(
"Insert") != StringRef::npos)) {
1157 S = getUnarySummary(FT, cfretain);
1159 S = getUnarySummary(FT, cfautorelease);
1162 AllowAnnotations =
false;
1164 S = getUnarySummary(FT, cfmakecollectable);
1165 AllowAnnotations =
false;
1167 S = getCFCreateGetRuleSummary(FD);
1176 S = getUnarySummary(FT, cfretain);
1178 S = getCFCreateGetRuleSummary(FD);
1187 S = getCFCreateGetRuleSummary(FD);
1191 if (FD->
hasAttr<CFAuditedTransferAttr>()) {
1192 S = getCFCreateGetRuleSummary(FD);
1201 if (FName[0] ==
'C' && (FName[1] ==
'F' || FName[1] ==
'G')) {
1203 FName = FName.substr(FName.startswith(
"CGCF") ? 4 : 2);
1206 S = getUnarySummary(FT, cfrelease);
1208 assert (ScratchArgs.isEmpty());
1224 ArgEffect E = (StrInStrNoCase(FName,
"InsertValue") != StringRef::npos||
1225 StrInStrNoCase(FName,
"AddValue") != StringRef::npos ||
1226 StrInStrNoCase(FName,
"SetValue") != StringRef::npos ||
1227 StrInStrNoCase(FName,
"AppendValue") != StringRef::npos||
1228 StrInStrNoCase(FName,
"SetAttribute") != StringRef::npos)
1239 S = getDefaultSummary();
1242 if (AllowAnnotations)
1243 updateSummaryFromAnnotations(S, FD);
1245 FuncSummaries[FD] =
S;
1249 const RetainSummary *
1250 RetainSummaryManager::getCFCreateGetRuleSummary(
const FunctionDecl *FD) {
1252 return getCFSummaryCreateRule(FD);
1254 return getCFSummaryGetRule(FD);
1257 const RetainSummary *
1258 RetainSummaryManager::getUnarySummary(
const FunctionType* FT,
1259 UnaryFuncKind func) {
1265 return getPersistentStopSummary();
1267 assert (ScratchArgs.isEmpty());
1271 case cfretain: Effect =
IncRef;
break;
1272 case cfrelease: Effect =
DecRef;
break;
1277 ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1281 const RetainSummary *
1282 RetainSummaryManager::getCFSummaryCreateRule(
const FunctionDecl *FD) {
1283 assert (ScratchArgs.isEmpty());
1285 return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF,
true));
1288 const RetainSummary *
1289 RetainSummaryManager::getCFSummaryGetRule(
const FunctionDecl *FD) {
1290 assert (ScratchArgs.isEmpty());
1291 return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1300 RetainSummaryManager::getRetEffectFromAnnotations(
QualType RetTy,
1303 if (D->
hasAttr<NSReturnsRetainedAttr>())
1304 return ObjCAllocRetE;
1306 if (D->
hasAttr<NSReturnsNotRetainedAttr>() ||
1307 D->
hasAttr<NSReturnsAutoreleasedAttr>())
1314 if (D->
hasAttr<CFReturnsRetainedAttr>())
1315 return RetEffect::MakeOwned(RetEffect::CF,
true);
1317 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
1318 return RetEffect::MakeNotOwned(RetEffect::CF);
1324 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1329 assert(Summ &&
"Must have a summary to add annotations to.");
1330 RetainSummaryTemplate Template(Summ, *
this);
1333 unsigned parm_idx = 0;
1335 pe = FD->
param_end(); pi != pe; ++pi, ++parm_idx) {
1337 if (pd->
hasAttr<NSConsumedAttr>())
1338 Template->addArg(AF, parm_idx,
DecRefMsg);
1339 else if (pd->
hasAttr<CFConsumedAttr>())
1340 Template->addArg(AF, parm_idx,
DecRef);
1341 else if (pd->
hasAttr<CFReturnsRetainedAttr>()) {
1346 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1356 Template->setRetEffect(*RetE);
1360 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1365 assert(Summ &&
"Must have a valid summary to add annotations to");
1366 RetainSummaryTemplate Template(Summ, *
this);
1369 if (MD->
hasAttr<NSConsumesSelfAttr>())
1373 unsigned parm_idx = 0;
1376 pi != pe; ++pi, ++parm_idx) {
1378 if (pd->
hasAttr<NSConsumedAttr>())
1379 Template->addArg(AF, parm_idx,
DecRefMsg);
1380 else if (pd->
hasAttr<CFConsumedAttr>()) {
1381 Template->addArg(AF, parm_idx,
DecRef);
1382 }
else if (pd->
hasAttr<CFReturnsRetainedAttr>()) {
1387 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1397 Template->setRetEffect(*RetE);
1400 const RetainSummary *
1401 RetainSummaryManager::getStandardMethodSummary(
const ObjCMethodDecl *MD,
1405 RetEffect ResultEff = RetEffect::MakeNoRet();
1428 ResultEff = RetEffect::MakeOwned(RetEffect::CF,
true);
1431 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1435 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1440 ResultEff = ObjCInitRetE;
1448 ResultEff = ObjCAllocRetE;
1450 ResultEff = RetEffect::MakeOwned(RetEffect::CF,
true);
1478 for (
unsigned i = 0, e = S.
getNumArgs(); i != e; ++i) {
1480 if (Slot.substr(Slot.size() - 8).equals_lower(
"delegate")) {
1481 if (ResultEff == ObjCInitRetE)
1482 ResultEff = RetEffect::MakeNoRetHard();
1489 if (ScratchArgs.isEmpty() && ReceiverEff ==
DoNothing &&
1490 ResultEff.
getKind() == RetEffect::NoRet)
1491 return getDefaultSummary();
1493 return getPersistentSummary(ResultEff, ReceiverEff,
MayEscape);
1496 const RetainSummary *
1497 RetainSummaryManager::getInstanceMethodSummary(
const ObjCMethodCall &Msg,
1511 ReceiverClass = PT->getInterfaceDecl();
1523 if (!Method && ReceiverClass)
1526 return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1527 ObjCMethodSummaries);
1530 const RetainSummary *
1533 ObjCMethodSummariesTy &CachedSummaries) {
1536 const RetainSummary *Summ = CachedSummaries.find(ID, S);
1539 Summ = getStandardMethodSummary(MD, S, RetTy);
1542 updateSummaryFromAnnotations(Summ, MD);
1545 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1551 void RetainSummaryManager::InitializeClassMethodSummaries() {
1552 assert(ScratchArgs.isEmpty());
1554 addClassMethSummary(
"NSAssertionHandler",
"currentHandler",
1558 ScratchArgs = AF.add(ScratchArgs, 0,
Autorelease);
1559 addClassMethSummary(
"NSAutoreleasePool",
"addObject",
1560 getPersistentSummary(RetEffect::MakeNoRet(),
1564 void RetainSummaryManager::InitializeMethodSummaries() {
1566 assert (ScratchArgs.isEmpty());
1570 const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE,
DecRefMsg);
1579 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1580 const RetainSummary *CFAllocSumm =
1581 getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF,
true));
1584 RetEffect NoRet = RetEffect::MakeNoRet();
1585 const RetainSummary *Summ = getPersistentSummary(NoRet,
IncRefMsg);
1589 Summ = getPersistentSummary(NoRet,
DecRefMsg);
1593 Summ = getPersistentSummary(NoRet,
Dealloc);
1606 const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1610 addClassMethSummary(
"NSWindow",
"alloc", NoTrackYet);
1616 addClassMethSummary(
"NSPanel",
"alloc", NoTrackYet);
1621 addClassMethSummary(
"NSNull",
"null", NoTrackYet);
1625 addClassMethSummary(
"NSAutoreleasePool",
"alloc", NoTrackYet);
1626 addClassMethSummary(
"NSAutoreleasePool",
"allocWithZone", NoTrackYet,
false);
1627 addClassMethSummary(
"NSAutoreleasePool",
"new", NoTrackYet);
1630 addInstMethSummary(
"QCRenderer", AllocSumm,
1631 "createSnapshotImageOfType",
nullptr);
1632 addInstMethSummary(
"QCView", AllocSumm,
1633 "createSnapshotImageOfType",
nullptr);
1638 addInstMethSummary(
"CIContext", CFAllocSumm,
1639 "createCGImage",
"fromRect",
nullptr);
1640 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect",
1641 "format",
"colorSpace",
nullptr);
1642 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGLayerWithSize",
"info",
1650 typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1657 class CFRefBug :
public BugType {
1659 CFRefBug(
const CheckerBase *checker, StringRef name)
1665 virtual const char *getDescription()
const = 0;
1667 virtual bool isLeak()
const {
return false; }
1670 class UseAfterRelease :
public CFRefBug {
1673 : CFRefBug(checker,
"Use-after-release") {}
1675 const char *getDescription()
const override {
1676 return "Reference-counted object is used after it is released";
1680 class BadRelease :
public CFRefBug {
1682 BadRelease(
const CheckerBase *checker) : CFRefBug(checker,
"Bad release") {}
1684 const char *getDescription()
const override {
1685 return "Incorrect decrement of the reference count of an object that is "
1686 "not owned at this point by the caller";
1690 class DeallocGC :
public CFRefBug {
1693 : CFRefBug(checker,
"-dealloc called while using garbage collection") {}
1695 const char *getDescription()
const override {
1696 return "-dealloc called while using garbage collection";
1700 class DeallocNotOwned :
public CFRefBug {
1703 : CFRefBug(checker,
"-dealloc sent to non-exclusively owned object") {}
1705 const char *getDescription()
const override {
1706 return "-dealloc sent to object that may be referenced elsewhere";
1710 class OverAutorelease :
public CFRefBug {
1713 : CFRefBug(checker,
"Object autoreleased too many times") {}
1715 const char *getDescription()
const override {
1716 return "Object autoreleased too many times";
1720 class ReturnedNotOwnedForOwned :
public CFRefBug {
1722 ReturnedNotOwnedForOwned(
const CheckerBase *checker)
1723 : CFRefBug(checker,
"Method should return an owned object") {}
1725 const char *getDescription()
const override {
1726 return "Object with a +0 retain count returned to caller where a +1 "
1727 "(owning) retain count is expected";
1731 class Leak :
public CFRefBug {
1733 Leak(
const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
1735 setSuppressOnSink(
true);
1738 const char *getDescription()
const override {
return ""; }
1740 bool isLeak()
const override {
return true; }
1750 const SummaryLogTy &SummaryLog;
1754 CFRefReportVisitor(
SymbolRef sym,
bool gcEnabled,
const SummaryLogTy &
log)
1755 : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1757 void Profile(llvm::FoldingSetNodeID &ID)
const override {
1773 class CFRefLeakReportVisitor :
public CFRefReportVisitor {
1775 CFRefLeakReportVisitor(
SymbolRef sym,
bool GCEnabled,
1776 const SummaryLogTy &
log)
1777 : CFRefReportVisitor(sym, GCEnabled, log) {}
1783 std::unique_ptr<BugReporterVisitor> clone()
const override {
1789 return llvm::make_unique<CFRefLeakReportVisitor>(*this);
1794 void addGCModeDescription(
const LangOptions &LOpts,
bool GCEnabled);
1797 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1799 bool registerVisitor =
true)
1801 if (registerVisitor)
1802 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1803 addGCModeDescription(LOpts, GCEnabled);
1806 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1809 :
BugReport(D, D.getDescription(), endText, n) {
1810 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1811 addGCModeDescription(LOpts, GCEnabled);
1814 llvm::iterator_range<ranges_iterator> getRanges()
override {
1815 const CFRefBug& BugTy =
static_cast<CFRefBug&
>(getBugType());
1816 if (!BugTy.isLeak())
1818 return llvm::make_range(ranges_iterator(), ranges_iterator());
1822 class CFRefLeakReport :
public CFRefReport {
1825 CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1828 bool IncludeAllocationLine);
1831 assert(Location.isValid());
1837 void CFRefReport::addGCModeDescription(
const LangOptions &LOpts,
1839 const char *GCModeDescription =
nullptr;
1841 switch (LOpts.getGC()) {
1844 GCModeDescription =
"Code is compiled to only use garbage collection";
1849 GCModeDescription =
"Code is compiled to use reference counts";
1854 GCModeDescription =
"Code is compiled to use either garbage collection "
1855 "(GC) or reference counts (non-GC). The bug occurs "
1859 GCModeDescription =
"Code is compiled to use either garbage collection "
1860 "(GC) or reference counts (non-GC). The bug occurs "
1866 assert(GCModeDescription &&
"invalid/unknown GC mode");
1867 addExtraText(GCModeDescription);
1872 return isa<IntegerLiteral>(E) ||
1873 isa<CharacterLiteral>(E) ||
1874 isa<FloatingLiteral>(E) ||
1875 isa<ObjCBoolLiteralExpr>(E) ||
1876 isa<CXXBoolLiteralExpr>(E);
1882 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->
getDecl());
1904 if (!CurrT)
return nullptr;
1906 const RefVal &CurrV = *CurrT;
1912 llvm::raw_string_ostream os(sbuf);
1919 if (isa<ObjCIvarRefExpr>(S) &&
1924 if (isa<ObjCArrayLiteral>(S)) {
1925 os <<
"NSArray literal is an object with a +0 retain count";
1927 else if (isa<ObjCDictionaryLiteral>(S)) {
1928 os <<
"NSDictionary literal is an object with a +0 retain count";
1930 else if (
const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1932 os <<
"NSNumber literal is an object with a +0 retain count";
1941 os << *BoxClass <<
" b";
1945 os <<
"oxed expression produces an object with a +0 retain count";
1948 else if (isa<ObjCIvarRefExpr>(S)) {
1949 os <<
"Object loaded from instance variable";
1952 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1954 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
1956 os <<
"Call to function '" << *FD <<
'\'';
1958 os <<
"function call";
1961 assert(isa<ObjCMessageExpr>(S));
1966 switch (Call->getMessageKind()) {
1979 if (CurrV.getObjKind() == RetEffect::CF) {
1980 os <<
" returns a Core Foundation object with a ";
1984 os <<
" returns an Objective-C object with a ";
1987 if (CurrV.isOwned()) {
1988 os <<
"+1 retain count";
1991 assert(CurrV.getObjKind() == RetEffect::CF);
1993 "Core Foundation objects are not automatically garbage collected.";
1997 assert (CurrV.isNotOwned());
1998 os <<
"+0 retain count";
2012 if (
const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
2017 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2023 AI!=AE; ++AI, ++i) {
2027 if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
2031 AEffects.push_back(Summ->getArg(i));
2035 if (
const Expr *receiver = ME->getInstanceReceiver())
2036 if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
2037 .getAsLocSymbol() == Sym) {
2039 AEffects.push_back(Summ->getReceiverEffect());
2046 RefVal PrevV = *PrevT;
2049 if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(),
Dealloc) !=
2052 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2055 if (CurrV.getKind() == RefVal::Released) {
2056 assert(CurrV.getCombinedCounts() == 0);
2057 os <<
"Object released by directly sending the '-dealloc' message";
2068 CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2073 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2075 os <<
"In GC mode a call to '" << *FD
2076 <<
"' decrements an object's retain count and registers the "
2077 "object with the garbage collector. ";
2079 if (CurrV.getKind() == RefVal::Released) {
2080 assert(CurrV.getCount() == 0);
2081 os <<
"Since it now has a 0 retain count the object can be "
2082 "automatically collected by the garbage collector.";
2085 os <<
"An object must have a 0 retain count to be garbage collected. "
2086 "After this call its retain count is +" << CurrV.getCount()
2090 os <<
"When GC is not enabled a call to '" << *FD
2091 <<
"' has no effect on its argument.";
2098 if (!PrevV.hasSameState(CurrV))
2099 switch (CurrV.getKind()) {
2101 case RefVal::NotOwned:
2102 if (PrevV.getCount() == CurrV.getCount()) {
2104 if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2107 assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2108 os <<
"Object autoreleased";
2112 if (PrevV.getCount() > CurrV.getCount())
2113 os <<
"Reference count decremented.";
2115 os <<
"Reference count incremented.";
2117 if (
unsigned Count = CurrV.getCount())
2118 os <<
" The object now has a +" <<
Count <<
" retain count.";
2120 if (PrevV.getKind() == RefVal::Released) {
2121 assert(GCEnabled && CurrV.getCount() > 0);
2122 os <<
" The object is not eligible for garbage collection until "
2123 "the retain count reaches 0 again.";
2128 case RefVal::Released:
2129 if (CurrV.getIvarAccessHistory() ==
2130 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
2131 CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
2132 os <<
"Strong instance variable relinquished. ";
2134 os <<
"Object released.";
2137 case RefVal::ReturnedOwned:
2139 if (CurrV.getAutoreleaseCount())
2142 os <<
"Object returned to caller as an owning reference (single "
2143 "retain count transferred to caller)";
2146 case RefVal::ReturnedNotOwned:
2147 os <<
"Object returned to caller with a +0 retain count";
2156 E=AEffects.end(); I != E; ++I) {
2163 os <<
"In GC mode an 'autorelease' has no effect.";
2166 os <<
"In GC mode the 'retain' message has no effect.";
2169 os <<
"In GC mode the 'release' message has no effect.";
2175 if (os.str().empty())
2185 for (
const Stmt *Child : S->children())
2186 if (
const Expr *Exp = dyn_cast_or_null<Expr>(Child))
2187 if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2188 P->
addRange(Exp->getSourceRange());
2207 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2214 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2215 const MemRegion *FirstBinding =
nullptr;
2251 if (NContext == LeakContext || NContext->
isParentOf(LeakContext))
2252 AllocationNodeInCurrentOrParentContext = N;
2256 if (!InitMethodContext)
2258 const Stmt *CE = CEP->getCallExpr();
2259 if (
const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2260 const Stmt *RecExpr = ME->getInstanceReceiver();
2262 SVal RecV = St->getSVal(RecExpr, NContext);
2264 InitMethodContext = CEP->getCalleeContext();
2275 if (InitMethodContext) {
2280 InterestingMethodContext = InitMethodContext;
2285 assert(N &&
"Could not find allocation node");
2287 FirstBinding =
nullptr;
2292 InterestingMethodContext);
2295 std::unique_ptr<PathDiagnosticPiece>
2302 std::unique_ptr<PathDiagnosticPiece>
2328 llvm::raw_string_ostream os(sbuf);
2330 os <<
"Object leaked: ";
2333 os <<
"object allocated and stored into '"
2334 << FirstBinding->getString() <<
'\'';
2337 os <<
"allocated object";
2343 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2349 os << (isa<ObjCMethodDecl>(D) ?
" is returned from a method "
2350 :
" is returned from a function ");
2352 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
2353 os <<
"that is annotated as CF_RETURNS_NOT_RETAINED";
2354 else if (D->
hasAttr<NSReturnsNotRetainedAttr>())
2355 os <<
"that is annotated as NS_RETURNS_NOT_RETAINED";
2359 <<
"') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2360 " This violates the naming convention rules"
2361 " given in the Memory Management Guide for Cocoa";
2365 os <<
"whose name ('" << *FD
2366 <<
"') does not contain 'Copy' or 'Create'. This violates the naming"
2367 " convention rules given in the Memory Management Guide for Core"
2372 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2375 <<
"' is potentially leaked when using garbage collection. Callers "
2376 "of this method do not expect a returned object with a +1 retain "
2377 "count since they expect the object to be managed by the garbage "
2381 os <<
" is not referenced later in this execution path and has a retain "
2382 "count of +" << RV->getCount();
2384 return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
2387 CFRefLeakReport::CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
2388 bool GCEnabled,
const SummaryLogTy &Log,
2391 bool IncludeAllocationLine)
2392 : CFRefReport(D, LOpts, GCEnabled, Log, n, sym,
false) {
2409 AllocNode = AllocI.
N;
2410 AllocBinding = AllocI.
R;
2417 const Stmt *AllocStmt = 0;
2420 AllocStmt = Exit->getCalleeContext()->getCallSite();
2423 assert(AllocStmt &&
"Cannot find allocation statement");
2426 PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2427 AllocNode->getLocationContext());
2428 Location = AllocLocation;
2432 UniqueingLocation = AllocLocation;
2433 UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2436 Description.clear();
2437 llvm::raw_string_ostream os(Description);
2438 os <<
"Potential leak ";
2440 os <<
"(when using garbage collection) ";
2441 os <<
"of an object";
2444 os <<
" stored into '" << AllocBinding->getString() <<
'\'';
2445 if (IncludeAllocationLine) {
2451 addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2459 class RetainCountChecker
2460 :
public Checker< check::Bind,
2464 check::PostStmt<BlockExpr>,
2465 check::PostStmt<CastExpr>,
2466 check::PostStmt<ObjCArrayLiteral>,
2467 check::PostStmt<ObjCDictionaryLiteral>,
2468 check::PostStmt<ObjCBoxedExpr>,
2469 check::PostStmt<ObjCIvarRefExpr>,
2471 check::PreStmt<ReturnStmt>,
2472 check::RegionChanges,
2475 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2476 mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2477 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2478 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2479 mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2481 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2484 mutable SymbolTagMap DeadSymbolTags;
2486 mutable std::unique_ptr<RetainSummaryManager> Summaries;
2487 mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2488 mutable SummaryLogTy SummaryLog;
2489 mutable bool ShouldResetSummaryLog;
2493 mutable bool IncludeAllocationLine;
2497 : ShouldResetSummaryLog(
false),
2500 ~RetainCountChecker()
override { DeleteContainerSeconds(DeadSymbolTags); }
2532 if (ShouldResetSummaryLog)
2535 ShouldResetSummaryLog = !SummaryLog.empty();
2538 CFRefBug *getLeakWithinFunctionBug(
const LangOptions &LOpts,
2539 bool GCEnabled)
const {
2541 if (!leakWithinFunctionGC)
2542 leakWithinFunctionGC.reset(
new Leak(
this,
"Leak of object when using "
2543 "garbage collection"));
2544 return leakWithinFunctionGC.get();
2546 if (!leakWithinFunction) {
2548 leakWithinFunction.reset(
new Leak(
this,
2549 "Leak of object when not using "
2550 "garbage collection (GC) in "
2551 "dual GC/non-GC code"));
2553 leakWithinFunction.reset(
new Leak(
this,
"Leak"));
2556 return leakWithinFunction.get();
2560 CFRefBug *getLeakAtReturnBug(
const LangOptions &LOpts,
bool GCEnabled)
const {
2562 if (!leakAtReturnGC)
2563 leakAtReturnGC.reset(
new Leak(
this,
2564 "Leak of returned object when using "
2565 "garbage collection"));
2566 return leakAtReturnGC.get();
2568 if (!leakAtReturn) {
2570 leakAtReturn.reset(
new Leak(
this,
2571 "Leak of returned object when not using "
2572 "garbage collection (GC) in dual "
2575 leakAtReturn.reset(
new Leak(
this,
"Leak of returned object"));
2578 return leakAtReturn.get();
2582 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx,
2583 bool GCEnabled)
const {
2589 SummariesGC.reset(
new RetainSummaryManager(Ctx,
true, ARCEnabled));
2591 assert(SummariesGC->isARCEnabled() == ARCEnabled);
2592 return *SummariesGC;
2595 Summaries.reset(
new RetainSummaryManager(Ctx,
false, ARCEnabled));
2597 assert(Summaries->isARCEnabled() == ARCEnabled);
2607 const char *NL,
const char *Sep)
const override;
2621 void checkSummary(
const RetainSummary &Summ,
const CallEvent &Call,
2624 void processSummaryOfInlined(
const RetainSummary &Summ,
2631 bool Assumption)
const;
2653 RefVal V,
ArgEffect E, RefVal::Kind &hasErr,
2688 state = state->remove<RefBindings>(sym);
2698 void RetainCountChecker::checkPostStmt(
const BlockExpr *BE,
2708 cast<BlockDataRegion>(state->getSVal(BE,
2724 for ( ; I != E; ++I) {
2725 const VarRegion *VR = I.getCapturedRegion();
2729 Regions.push_back(VR);
2733 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2734 Regions.data() + Regions.size()).getState();
2738 void RetainCountChecker::checkPostStmt(
const CastExpr *CE,
2767 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2778 const Expr *Ex)
const {
2781 for (
const Stmt *Child : Ex->children()) {
2786 state = updateSymbol(state, sym, *T,
MayEscape, hasErr, C);
2788 processNonLeakError(state, Child->getSourceRange(), hasErr, sym,
C);
2809 processObjCLiterals(C, AL);
2815 processObjCLiterals(C, DL);
2818 void RetainCountChecker::checkPostStmt(
const ObjCBoxedExpr *Ex,
2824 if (
SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2834 if (
auto DerivedVal = dyn_cast<SymbolDerived>(Sym))
2835 return isa<ObjCIvarRegion>(DerivedVal->getRegion());
2836 if (
auto RegionVal = dyn_cast<SymbolRegionValue>(Sym))
2837 return isa<ObjCIvarRegion>(RegionVal->getRegion());
2848 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2860 Kind = RetEffect::CF;
2872 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2882 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2890 State =
setRefBinding(State, Sym, PlusZero.withIvarAccess());
2894 void RetainCountChecker::checkPostCall(
const CallEvent &Call,
2896 RetainSummaryManager &Summaries = getSummaryManager(C);
2897 const RetainSummary *Summ = Summaries.getSummary(Call, C.
getState());
2900 processSummaryOfInlined(*Summ, Call, C);
2903 checkSummary(*Summ, Call, C);
2920 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2921 PT->isObjCClassType()) {
2937 void RetainCountChecker::processSummaryOfInlined(
const RetainSummary &Summ,
2943 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
2954 if (MsgInvocation) {
2964 if (RE.
getKind() == RetEffect::NoRetHard) {
2976 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.
getAsRegion());
2980 QualType PointeeTy = ArgRegion->getValueType();
2984 SVal PointeeVal = State->getSVal(ArgRegion);
2992 RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
3001 llvm_unreachable(
"only for out parameters");
3007 void RetainCountChecker::checkSummary(
const RetainSummary &Summ,
3017 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3025 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3036 bool ReceiverIsTracked =
false;
3039 if (MsgInvocation) {
3042 ReceiverIsTracked =
true;
3043 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3056 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3063 if (RE.
getKind() == RetEffect::OwnedWhenTrackedReceiver) {
3064 if (ReceiverIsTracked)
3065 RE = getSummaryManager(C).getObjAllocRetEffect();
3067 RE = RetEffect::MakeNoRet();
3072 llvm_unreachable(
"Unhandled RetEffect.");
3074 case RetEffect::NoRet:
3075 case RetEffect::NoRetHard:
3079 case RetEffect::OwnedAllocatedSymbol:
3080 case RetEffect::OwnedSymbol: {
3096 case RetEffect::GCNotOwnedSymbol:
3097 case RetEffect::NotOwnedSymbol: {
3124 if (ShouldResetSummaryLog) {
3126 ShouldResetSummaryLog =
false;
3128 SummaryLog[NewNode] = &Summ;
3135 RefVal V,
ArgEffect E, RefVal::Kind &hasErr,
3140 if (!IgnoreRetainMsg)
3162 V = V ^ RefVal::ErrorUseAfterRelease;
3163 hasErr = V.getKind();
3172 llvm_unreachable(
"DecRefMsg/IncRefMsg/MakeCollectable already converted");
3176 llvm_unreachable(
"Applies to pointer-to-pointer parameters, which should "
3177 "not have ref state.");
3182 V = V ^ RefVal::ErrorDeallocGC;
3183 hasErr = V.getKind();
3187 switch (V.getKind()) {
3189 llvm_unreachable(
"Invalid RefVal state for an explicit dealloc.");
3192 V = V ^ RefVal::Released;
3195 case RefVal::NotOwned:
3196 V = V ^ RefVal::ErrorDeallocNotOwned;
3197 hasErr = V.getKind();
3203 if (V.getKind() == RefVal::Owned) {
3204 V = V ^ RefVal::NotOwned;
3217 V = V.autorelease();
3225 switch (V.getKind()) {
3227 llvm_unreachable(
"Invalid RefVal state for a retain.");
3229 case RefVal::NotOwned:
3232 case RefVal::Released:
3235 V = (V ^ RefVal::Owned) + 1;
3243 switch (V.getKind()) {
3246 llvm_unreachable(
"Invalid RefVal state for a release.");
3249 assert(V.getCount() > 0);
3250 if (V.getCount() == 1) {
3252 V.getIvarAccessHistory() ==
3253 RefVal::IvarAccessHistory::AccessedDirectly)
3254 V = V ^ RefVal::NotOwned;
3256 V = V ^ RefVal::Released;
3264 case RefVal::NotOwned:
3265 if (V.getCount() > 0) {
3269 }
else if (V.getIvarAccessHistory() ==
3270 RefVal::IvarAccessHistory::AccessedDirectly) {
3275 V = V.releaseViaIvar() ^ RefVal::Released;
3277 V = V ^ RefVal::ErrorReleaseNotOwned;
3278 hasErr = V.getKind();
3282 case RefVal::Released:
3285 V = V ^ RefVal::ErrorUseAfterRelease;
3286 hasErr = V.getKind();
3296 RefVal::Kind ErrorKind,
3306 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3314 switch (ErrorKind) {
3316 llvm_unreachable(
"Unhandled error.");
3317 case RefVal::ErrorUseAfterRelease:
3318 if (!useAfterRelease)
3319 useAfterRelease.reset(
new UseAfterRelease(
this));
3320 BT = useAfterRelease.get();
3322 case RefVal::ErrorReleaseNotOwned:
3323 if (!releaseNotOwned)
3324 releaseNotOwned.reset(
new BadRelease(
this));
3325 BT = releaseNotOwned.get();
3327 case RefVal::ErrorDeallocGC:
3329 deallocGC.reset(
new DeallocGC(
this));
3330 BT = deallocGC.get();
3332 case RefVal::ErrorDeallocNotOwned:
3333 if (!deallocNotOwned)
3334 deallocNotOwned.reset(
new DeallocNotOwned(
this));
3335 BT = deallocNotOwned.get();
3340 auto report = std::unique_ptr<BugReport>(
3342 SummaryLog, N, Sym));
3343 report->addRange(ErrorRange);
3370 StringRef FName = II->
getName();
3371 FName = FName.substr(FName.find_first_not_of(
'_'));
3374 bool canEval =
false;
3379 canEval = II->
isStr(
"NSMakeCollectable");
3397 SVal RetVal = state->getSVal(CE->
getArg(0), LCtx);
3403 state = state->BindExpr(CE, LCtx, RetVal,
false);
3410 const RefVal *Binding =
nullptr;
3415 state = state->invalidateRegions(ArgRegion, CE, C.
blockCount(), LCtx,
3431 void RetainCountChecker::checkPreStmt(
const ReturnStmt *S,
3460 switch (X.getKind()) {
3461 case RefVal::Owned: {
3462 unsigned cnt = X.getCount();
3464 X.setCount(cnt - 1);
3465 X = X ^ RefVal::ReturnedOwned;
3469 case RefVal::NotOwned: {
3470 unsigned cnt = X.getCount();
3472 X.setCount(cnt - 1);
3473 X = X ^ RefVal::ReturnedOwned;
3476 X = X ^ RefVal::ReturnedNotOwned;
3499 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3511 RetainSummaryManager &Summaries = getSummaryManager(C);
3517 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3518 RE = Summ->getRetEffect();
3519 }
else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3520 if (!isa<CXXMethodDecl>(FD)) {
3521 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3522 RE = Summ->getRetEffect();
3526 checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3529 void RetainCountChecker::checkReturnWithRetEffect(
const ReturnStmt *S,
3541 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3545 if (X.isReturnedOwned() && X.getCount() == 0) {
3546 if (RE.
getKind() != RetEffect::NoRet) {
3547 bool hasError =
false;
3554 X = X ^ RefVal::ErrorGCLeakReturned;
3561 X = X ^ RefVal::ErrorLeakReturned;
3573 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefLeakReport(
3574 *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3575 SummaryLog, N, Sym, C, IncludeAllocationLine)));
3579 }
else if (X.isReturnedNotOwned()) {
3581 if (X.getIvarAccessHistory() ==
3582 RefVal::IvarAccessHistory::AccessedDirectly) {
3586 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3590 state =
setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3593 ReturnNotOwnedTag(
this,
"ReturnNotOwnedForOwned");
3597 if (!returnNotOwnedForOwned)
3598 returnNotOwnedForOwned.reset(
new ReturnedNotOwnedForOwned(
this));
3600 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefReport(
3613 void RetainCountChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
3616 bool escapes =
true;
3627 escapes = !regionLoc->getRegion()->hasStackStorage();
3635 SVal StoredVal = state->getSVal(regionLoc->getRegion());
3636 if (StoredVal != val)
3637 escapes = (state == (state->bindLoc(*regionLoc, val)));
3643 escapes = !isa<VarRegion>(regionLoc->getRegion());
3651 const VarDecl *VD = LVR->getDecl();
3652 if (VD->
hasAttr<CleanupAttr>()) {
3665 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3671 bool Assumption)
const {
3679 RefBindingsTy B = state->get<RefBindings>();
3684 bool changed =
false;
3685 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
3687 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3693 B = RefBFactory.remove(B, I.getKey());
3698 state = state->set<RefBindings>(B);
3712 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3714 E = ExplicitRegions.end(); I != E; ++I) {
3716 WhitelistedSymbols.insert(SR->getSymbol());
3719 for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3720 E = invalidated->end(); I!=E; ++I) {
3722 if (WhitelistedSymbols.count(sym))
3740 unsigned ACnt = V.getAutoreleaseCount();
3747 unsigned Cnt = V.getCount();
3751 if (V.getKind() == RefVal::ReturnedOwned)
3757 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
3758 V = V.releaseViaIvar();
3765 if (V.getKind() == RefVal::ReturnedOwned)
3766 V = V ^ RefVal::ReturnedNotOwned;
3768 V = V ^ RefVal::NotOwned;
3770 V.setCount(V.getCount() - ACnt);
3771 V.setAutoreleaseCount(0);
3782 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3787 V = V ^ RefVal::ErrorOverAutorelease;
3793 llvm::raw_svector_ostream os(sbuf);
3794 os <<
"Object was autoreleased ";
3795 if (V.getAutoreleaseCount() > 1)
3796 os << V.getAutoreleaseCount() <<
" times but the object ";
3799 os <<
"has a +" << V.getCount() <<
" retain count";
3801 if (!overAutorelease)
3802 overAutorelease.reset(
new OverAutorelease(
this));
3806 new CFRefReport(*overAutorelease, LOpts,
false,
3807 SummaryLog, N, Sym, os.str())));
3825 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3827 else if (V.isOwned())
3829 else if (V.isNotOwned() || V.isReturnedOwned())
3830 hasLeak = (V.getCount() > 0);
3837 Leaked.push_back(sid);
3851 I = Leaked.begin(), E = Leaked.end(); I != E; ++I) {
3855 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3856 : getLeakAtReturnBug(LOpts, GCEnabled);
3857 assert(BT &&
"BugType not initialized.");
3860 new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
3861 IncludeAllocationLine)));
3868 void RetainCountChecker::checkEndFunction(
CheckerContext &Ctx)
const {
3870 RefBindingsTy B = state->get<RefBindings>();
3880 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3881 state = handleAutoreleaseCounts(state, Pred,
nullptr, Ctx,
3882 I->first, I->second);
3894 B = state->get<RefBindings>();
3897 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I)
3898 state = handleSymbolDeath(state, I->first, I->second, Leaked);
3900 processLeaks(state, Leaked, Ctx, Pred);
3904 RetainCountChecker::getDeadSymbolTag(
SymbolRef sym)
const {
3908 llvm::raw_svector_ostream out(buf);
3909 out <<
"Dead Symbol : ";
3916 void RetainCountChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
3921 RefBindingsTy B = state->get<RefBindings>();
3926 E = SymReaper.
dead_end(); I != E; ++I) {
3928 if (
const RefVal *T = B.lookup(Sym)){
3932 state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
3938 state = handleSymbolDeath(state, *I, *
getRefBinding(state, Sym), Leaked);
3942 if (Leaked.empty()) {
3947 Pred = processLeaks(state, Leaked, C, Pred);
3955 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
3956 B = state->get<RefBindings>();
3961 B = F.remove(B, *I);
3963 state = state->set<RefBindings>(B);
3967 void RetainCountChecker::printState(raw_ostream &Out,
ProgramStateRef State,
3968 const char *NL,
const char *Sep)
const {
3970 RefBindingsTy B = State->get<RefBindings>();
3977 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
3978 Out << I->first <<
" : ";
3979 I->second.print(Out);
3996 namespace clang {
namespace ento {
namespace objc_retain {
4001 #define createCallEffect(D, KIND)\
4002 ASTContext &Ctx = D->getASTContext();\
4003 LangOptions L = Ctx.getLangOpts();\
4004 RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
4005 const RetainSummary *S = M.get ## KIND ## Summary(D);\
4006 CallEffects CE(S->getRetEffect());\
4007 CE.Receiver = S->getReceiverEffect();\
4008 unsigned N = D->param_size();\
4009 for (unsigned i = 0; i < N; ++i) {\
4010 CE.Args.push_back(S->getArg(i));\
4023 #undef createCallEffect
virtual SVal getArgSVal(unsigned Index) const
Returns the value of a given argument at the time of the call.
param_const_iterator param_begin() const
static Selector GetNullarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing a nullary selector.
ParmVarDecl *const * param_const_iterator
Smart pointer class that efficiently represents Objective-C method names.
MemRegion - The root abstract class for all memory regions.
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
ObjCInterfaceDecl * getClassInterface()
bool isInstanceMessage() const
static Selector GetUnarySelector(StringRef name, ASTContext &Ctx)
Utility function for constructing an unary selector.
bool operator==(CanQual< T > x, CanQual< U > y)
IdentifierInfo * getIdentifier() const
Bridging via __bridge, which does nothing but reinterpret the bits.
static ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym)
const StackFrameContext * getStackFrame() const
Defines the SourceManager interface.
ProgramPoint getLocation() const
getLocation - Returns the edge associated with the given node.
ExplodedNode * addTransition(ProgramStateRef State=nullptr, const ProgramPointTag *Tag=nullptr)
Generates a new transition in the program state graph (ExplodedGraph). Uses the default CheckerContex...
Manages the lifetime of CallEvent objects.
const RegionTy * getAs() const
bool isCocoaObjectRef(QualType T)
llvm::DenseMap< Stmt *, Stmt * > MapTy
static Selector getKeywordSelector(ASTContext &Ctx, va_list argp)
static RetEffect MakeNoRet()
referenced_vars_iterator referenced_vars_begin() const
ExplodedNode * getPredecessor()
Returns the previous node in the exploded graph, which includes the state of the program before the c...
const MemRegion * getBaseRegion() const
void addRange(SourceRange R)
ParmVarDecl - Represents a parameter to a function.
bool isObjCRetainableType() const
const LocationContext * InterestingMethodContext
const char *const MemoryCoreFoundationObjectiveC
referenced_vars_iterator referenced_vars_end() const
Symbolic value. These values used to capture symbolic execution of the program.
unsigned getNumParams() const
ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym)
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
static RetEffect MakeNoRetHard()
MemRegionManager & getRegionManager()
bool isBodyAutosynthesized() const
Checks if the body of the Decl is generated by the BodyFarm.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static bool wasLoadedFromIvar(SymbolRef Sym)
const FunctionDecl * getCalleeDecl(const CallExpr *CE) const
Get the declaration of the called function (path-sensitive).
QualType getReturnType() const
bool isKeywordSelector() const
AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call. May be null.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef. Otherwise return 0...
const MemRegion * getRegion()
unsigned blockCount() const
Returns the number of times the current block has been visited along the analyzed path...
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
const FunctionDecl * getAsFunctionDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static ObjCSummaryKey getTombstoneKey()
static bool isRetain(const FunctionDecl *FD, StringRef FName)
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)
const VarDecl * getDecl() const
virtual llvm::iterator_range< ranges_iterator > getRanges()
Get the SourceRanges associated with the report.
static bool isEqual(const ObjCSummaryKey &LHS, const ObjCSummaryKey &RHS)
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.
SVal getReceiverSVal() const
Returns the value of the receiver at the time of this call.
const LangOptions & getLangOpts() const
ObjCBridgeCastKind getBridgeKind() const
Determine which kind of bridge is being performed via this cast.
static void Profile(const ArgEffect X, FoldingSetNodeID &ID)
ProgramStateManager & getStateManager()
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
QualType getReturnType() const
const Stmt * getCallSite() const
bool isParentOf(const LocationContext *LC) const
dead_iterator dead_begin() const
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)
virtual BugReport::NodeResolver & getNodeResolver()=0
virtual QualType getType() const =0
virtual SourceRange getArgSourceRange(unsigned Index) const
Returns the source range for errors associated with this argument.
param_iterator param_begin()
const MemRegion * getSuperRegion() const
const LocationContext * getLocationContext() const
const ParmVarDecl *const * param_const_iterator
ExplodedNode * generateSink(ProgramStateRef State=nullptr, ExplodedNode *Pred=nullptr, const ProgramPointTag *Tag=nullptr)
Generate a sink node. Generating a sink stops exploration of the given path.
llvm::ImmutableMap< unsigned, ArgEffect > ArgEffects
const MemRegion * StripCasts(bool StripBaseCasts=true) const
ID
Defines the set of possible language-specific address spaces.
QualType getPointeeType() const
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
const ProgramStateRef & getState() const
Defines the clang::LangOptions interface.
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
unsigned getNumArgs() const
SourceRange getReceiverRange() const
Source range of the receiver.
bool shouldIncludeAllocationSiteInLeakDiagnostics(AnalyzerOptions &AOpts)
Returns true if leak diagnostics should directly reference the allocatin site (where possible)...
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
SymbolSetTy::const_iterator dead_iterator
static CallEffects getEffect(const ObjCMethodDecl *MD)
Return the CallEfect for a given Objective-C method.
static bool isRelease(const FunctionDecl *FD, StringRef FName)
bool isObjCIdType() const
ObjKind
Determines the object kind of a tracked object.
bool isInstanceMethod() const
static RetEffect MakeOwned(ObjKind o, bool isAllocated=false)
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
static bool isAutorelease(const FunctionDecl *FD, StringRef FName)
bool isCFObjectRef(QualType T)
An expression that sends a message to the given Objective-C object or class.
void markInteresting(SymbolRef sym)
CallEventRef< ObjCMethodCall > getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State, const LocationContext *LCtx)
Represents a C function or static C++ member function call.
static bool isSynthesizedAccessor(const StackFrameContext *SFC)
param_const_iterator param_end() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
bool isConsumedExpr(Expr *E) const
static std::unique_ptr< PathDiagnosticPiece > getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR)
Generates the default final diagnostic piece.
CHECKER * registerChecker()
Used to register checkers.
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)
Create a new symbol with a unique 'name'.
static ObjCSummaryKey getEmptyKey()
const StackFrameContext * getCurrentStackFrame() const
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
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)
unsigned getSpellingLineNumber(bool *Invalid=nullptr) const
Selector getSelector() const
bool isPropertyAccessor() const
dead_iterator dead_end() const
#define va_start(ap, param)
std::string getAsString() const
Derive the full selector name (e.g. "foo:bar:") and return it as an std::string.
const Decl * getDecl() const
A class responsible for cleaning up unused symbols.
QualType getReturnType() const
const StackFrameContext * getStackFrame() const
REGISTER_MAP_WITH_PROGRAMSTATE(AllocatedData, SymbolRef, MacOSKeychainAPIChecker::AllocationState) static bool isEnclosingFunctionParam(const Expr *E)
const BlockDecl * getBlockDecl() const
const ObjCMethodDecl * getDecl() const override
QualType getCallReturnType(const ASTContext &Ctx) const
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
An Objective-C "bridged" cast expression, which casts between Objective-C pointers and C pointers...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(T-> getSizeExpr()))
static ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val)
const LocationContext * getParent() const
bool isRefType(QualType RetTy, StringRef Prefix, StringRef Name=StringRef())
ASTContext & getASTContext()
const Decl & getCodeDecl() const
virtual bool VisitSymbol(SymbolRef sym)=0
A visitor method invoked by ProgramStateManager::scanReachableSymbols.
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
const VarRegion * getVarRegion(const VarDecl *D, const LocationContext *LC)
__builtin_va_list va_list
AllocationInfo(const ExplodedNode *InN, const MemRegion *InR, const LocationContext *InInterestingMethodContext)
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
Selector getSelector() const
const MemRegion * getAsRegion() const
ObjCMethodFamily getMethodFamily() const
Derive the conventional family of this method.
const Expr * getRetValue() const
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
unsigned getNumArgs() const
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.
Optional< T > getAs() const
Convert to the specified ProgramPoint type, returning None if this ProgramPoint is not of the desired...
AnalyzerOptions & getAnalyzerOptions()
param_iterator param_end()
static ArgEffect getStopTrackingHardEquivalent(ArgEffect E)
virtual void dumpToStream(raw_ostream &os) const
QualType getResultType() const
Returns the result type, adjusted for references.
#define createCallEffect(D, KIND)
ProgramStateManager & getStateManager()
static bool isMakeCollectable(const FunctionDecl *FD, StringRef FName)
ObjCIvarRefExpr - A reference to an ObjC instance variable.
No particular method family.
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
ObjKind getObjKind() const
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)
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef. Otherwise, return 0.
bool isObjCGCEnabled() const
SValBuilder & getSValBuilder()
A SourceLocation and its associated SourceManager.
ObjCInterfaceDecl * getSuperClass() const
static Decl::Kind getKind(const Decl *D)
virtual const ExplodedNode * getOriginalNode(const ExplodedNode *N)=0
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
bool hasNonZeroCallbackArg() const
Returns true if any of the arguments appear to represent callbacks.
static unsigned getHashValue(const ObjCSummaryKey &V)
bool isNull() const
isNull - Return true if this QualType doesn't point to a type yet.
virtual const ObjCMessageExpr * getOriginExpr() const
SVal getReturnValue() const
Returns the return value of the call.
This class handles loading and caching of source files into memory.
SourceManager & getSourceManager()
static QualType GetReturnType(const Expr *RetE, ASTContext &Ctx)
const LocationContext * getLocationContext() const
SVal getSVal(const Stmt *S) const
Get the value of arbitrary expressions at this point in the path.
bool isPointerType() const