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);
238 RefVal releaseViaIvar()
const {
239 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
240 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
241 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
246 bool hasSameState(
const RefVal &
X)
const {
247 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
248 getIvarAccessHistory() == X.getIvarAccessHistory();
252 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
255 void Profile(llvm::FoldingSetNodeID&
ID)
const {
257 ID.AddInteger(RawKind);
260 ID.AddInteger(RawObjectKind);
261 ID.AddInteger(RawIvarAccessHistory);
264 void print(raw_ostream &Out)
const;
267 void RefVal::print(raw_ostream &Out)
const {
269 Out <<
"Tracked " << T.getAsString() <<
'/';
272 default: llvm_unreachable(
"Invalid RefVal kind");
275 unsigned cnt = getCount();
276 if (cnt) Out <<
" (+ " << cnt <<
")";
282 unsigned cnt = getCount();
283 if (cnt) Out <<
" (+ " << cnt <<
")";
287 case ReturnedOwned: {
288 Out <<
"ReturnedOwned";
289 unsigned cnt = getCount();
290 if (cnt) Out <<
" (+ " << cnt <<
")";
294 case ReturnedNotOwned: {
295 Out <<
"ReturnedNotOwned";
296 unsigned cnt = getCount();
297 if (cnt) Out <<
" (+ " << cnt <<
")";
306 Out <<
"-dealloc (GC)";
309 case ErrorDeallocNotOwned:
310 Out <<
"-dealloc (not-owned)";
317 case ErrorLeakReturned:
318 Out <<
"Leaked (Bad naming)";
321 case ErrorGCLeakReturned:
322 Out <<
"Leaked (GC-ed at return)";
325 case ErrorUseAfterRelease:
326 Out <<
"Use-After-Release [ERROR]";
329 case ErrorReleaseNotOwned:
330 Out <<
"Release of Not-Owned [ERROR]";
333 case RefVal::ErrorOverAutorelease:
334 Out <<
"Over-autoreleased";
337 case RefVal::ErrorReturnedNotOwned:
338 Out <<
"Non-owned object returned instead of owned";
342 switch (getIvarAccessHistory()) {
345 case IvarAccessHistory::AccessedDirectly:
346 Out <<
" [direct ivar access]";
348 case IvarAccessHistory::ReleasedAfterDirectAccess:
349 Out <<
" [released after direct ivar access]";
353 Out <<
" [autorelease -" << ACnt <<
']';
366 return State->get<RefBindings>(Sym);
371 return State->set<RefBindings>(Sym, Val);
375 return State->remove<RefBindings>(Sym);
383 class RetainSummary {
404 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
409 if (
const ArgEffect *AE = Args.lookup(idx))
412 return DefaultArgEffect;
415 void addArg(ArgEffects::Factory &af,
unsigned idx,
ArgEffect e) {
416 Args = af.add(Args, idx, e);
421 DefaultArgEffect =
E;
425 RetEffect getRetEffect()
const {
return Ret; }
432 void setReceiverEffect(
ArgEffect e) { Receiver = e; }
436 ArgEffect getReceiverEffect()
const {
return Receiver; }
441 bool operator==(
const RetainSummary &Other)
const {
442 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
443 Receiver == Other.Receiver && Ret == Other.Ret;
447 void Profile(llvm::FoldingSetNodeID&
ID)
const {
449 ID.Add(DefaultArgEffect);
455 bool isSimple()
const {
456 return Args.isEmpty();
460 ArgEffects getArgEffects()
const {
return Args; }
461 ArgEffect getDefaultArgEffect()
const {
return DefaultArgEffect; }
463 friend class RetainSummaryManager;
472 class ObjCSummaryKey {
483 : II(nullptr),
S(s) {}
486 Selector getSelector()
const {
return S; }
503 typedef std::pair<IdentifierInfo*, Selector> PairTy;
508 static bool isEqual(
const ObjCSummaryKey& LHS,
const ObjCSummaryKey& RHS) {
509 return LHS.getIdentifier() == RHS.getIdentifier() &&
510 LHS.getSelector() == RHS.getSelector();
517 class ObjCSummaryCache {
518 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *>
MapTy;
521 ObjCSummaryCache() {}
526 ObjCSummaryKey K(D, S);
541 if ((I = M.find(ObjCSummaryKey(
C, S))) != M.end())
550 const RetainSummary *Summ = I->second;
561 I = M.find(ObjCSummaryKey(S));
563 return I == M.end() ?
nullptr : I->second;
566 const RetainSummary *& operator[](ObjCSummaryKey K) {
570 const RetainSummary *& operator[](
Selector S) {
571 return M[ ObjCSummaryKey(S) ];
581 class RetainSummaryManager {
587 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
590 typedef ObjCSummaryCache ObjCMethodSummariesTy;
592 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
602 const bool GCEnabled;
605 const bool ARCEnabled;
608 FuncSummariesTy FuncSummaries;
612 ObjCMethodSummariesTy ObjCClassMethodSummaries;
615 ObjCMethodSummariesTy ObjCMethodSummaries;
619 llvm::BumpPtrAllocator BPAlloc;
622 ArgEffects::Factory AF;
637 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
647 enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
649 const RetainSummary *getUnarySummary(
const FunctionType* FT,
652 const RetainSummary *getCFSummaryCreateRule(
const FunctionDecl *FD);
653 const RetainSummary *getCFSummaryGetRule(
const FunctionDecl *FD);
654 const RetainSummary *getCFCreateGetRuleSummary(
const FunctionDecl *FD);
656 const RetainSummary *getPersistentSummary(
const RetainSummary &OldSumm);
658 const RetainSummary *getPersistentSummary(
RetEffect RetEff,
661 RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
662 return getPersistentSummary(Summ);
665 const RetainSummary *getDoNothingSummary() {
669 const RetainSummary *getDefaultSummary() {
674 const RetainSummary *getPersistentStopSummary() {
679 void InitializeClassMethodSummaries();
680 void InitializeMethodSummaries();
682 void addNSObjectClsMethSummary(
Selector S,
const RetainSummary *Summ) {
683 ObjCClassMethodSummaries[
S] = Summ;
686 void addNSObjectMethSummary(
Selector S,
const RetainSummary *Summ) {
687 ObjCMethodSummaries[
S] = Summ;
690 void addClassMethSummary(
const char* Cls,
const char* name,
691 const RetainSummary *Summ,
bool isNullary =
true) {
695 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
698 void addInstMethSummary(
const char* Cls,
const char* nullaryName,
699 const RetainSummary *Summ) {
702 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
705 void addMethodSummary(
IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
706 const RetainSummary *Summ,
va_list argp) {
708 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
711 void addInstMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
714 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
718 void addClsMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
721 addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
725 void addClsMethSummary(
IdentifierInfo *II,
const RetainSummary * Summ, ...) {
728 addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
734 RetainSummaryManager(
ASTContext &ctx,
bool gcenabled,
bool usesARC)
736 GCEnabled(gcenabled),
738 AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
739 ObjCAllocRetE(gcenabled
743 ObjCInitRetE(gcenabled
746 :
RetEffect::MakeOwnedWhenTrackedReceiver())) {
747 InitializeClassMethodSummaries();
748 InitializeMethodSummaries();
751 const RetainSummary *getSummary(
const CallEvent &Call,
754 const RetainSummary *getFunctionSummary(
const FunctionDecl *FD);
759 ObjCMethodSummariesTy &CachedSummaries);
761 const RetainSummary *getInstanceMethodSummary(
const ObjCMethodCall &M,
764 const RetainSummary *getClassMethodSummary(
const ObjCMethodCall &M) {
769 M.getResultType(), ObjCClassMethodSummaries);
779 ObjCMethodSummariesTy *CachedSummaries;
781 CachedSummaries = &ObjCMethodSummaries;
783 CachedSummaries = &ObjCClassMethodSummaries;
785 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
788 const RetainSummary *getStandardMethodSummary(
const ObjCMethodDecl *MD,
795 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
798 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
801 void updateSummaryForCall(
const RetainSummary *&Summ,
804 bool isGCEnabled()
const {
return GCEnabled; }
806 bool isARCEnabled()
const {
return ARCEnabled; }
808 bool isARCorGCEnabled()
const {
return GCEnabled || ARCEnabled; }
810 RetEffect getObjAllocRetEffect()
const {
return ObjCAllocRetE; }
812 friend class RetainSummaryTemplate;
819 class RetainSummaryTemplate {
820 RetainSummaryManager &Manager;
821 const RetainSummary *&RealSummary;
822 RetainSummary ScratchSummary;
825 RetainSummaryTemplate(
const RetainSummary *&real, RetainSummaryManager &mgr)
826 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(
false) {}
828 ~RetainSummaryTemplate() {
830 RealSummary = Manager.getPersistentSummary(ScratchSummary);
835 return ScratchSummary;
838 RetainSummary *operator->() {
840 return &ScratchSummary;
850 ArgEffects RetainSummaryManager::getArgEffects() {
852 ScratchArgs = AF.getEmptyMap();
856 const RetainSummary *
857 RetainSummaryManager::getPersistentSummary(
const RetainSummary &OldSumm) {
859 if (OldSumm.isSimple()) {
860 llvm::FoldingSetNodeID
ID;
864 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
867 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
868 new (N) CachedSummaryNode(OldSumm);
869 SimpleSummaries.InsertNode(N, Pos);
872 return &N->getValue();
875 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
876 new (Summ) RetainSummary(OldSumm);
885 return FName.endswith(
"Retain");
889 return FName.endswith(
"Release");
893 return FName.endswith(
"Autorelease");
899 return FName.find(
"MakeCollectable") != StringRef::npos;
926 llvm_unreachable(
"Unknown ArgEffect kind");
929 void RetainSummaryManager::updateSummaryForCall(
const RetainSummary *&S,
937 ArgEffects CustomArgEffects = S->getArgEffects();
939 E = CustomArgEffects.end();
942 if (Translated != DefEffect)
943 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
955 if (
Name->
isStr(
"CGBitmapContextCreateWithData"))
956 RE = S->getRetEffect();
960 S = getPersistentSummary(RE, RecEffect, DefEffect);
976 if (MC->getMethodFamily() ==
OMF_init && MC->isReceiverSelfOrSuper()) {
980 const Expr *ME = MC->getOriginExpr();
984 RetainSummaryTemplate ModifiableSummaryTemplate(S, *
this);
985 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();
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());
2201 struct AllocationInfo {
2208 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2212 static AllocationInfo
2216 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2217 const MemRegion *FirstBinding =
nullptr;
2253 if (NContext == LeakContext || NContext->
isParentOf(LeakContext))
2254 AllocationNodeInCurrentOrParentContext = N;
2258 if (!InitMethodContext)
2260 const Stmt *CE = CEP->getCallExpr();
2261 if (
const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2262 const Stmt *RecExpr = ME->getInstanceReceiver();
2264 SVal RecV = St->getSVal(RecExpr, NContext);
2266 InitMethodContext = CEP->getCalleeContext();
2277 if (InitMethodContext) {
2282 InterestingMethodContext = InitMethodContext;
2287 assert(N &&
"Could not find allocation node");
2289 FirstBinding =
nullptr;
2292 return AllocationInfo(AllocationNodeInCurrentOrParentContext,
2294 InterestingMethodContext);
2297 std::unique_ptr<PathDiagnosticPiece>
2304 std::unique_ptr<PathDiagnosticPiece>
2315 AllocationInfo AllocI =
2318 const MemRegion* FirstBinding = AllocI.R;
2330 llvm::raw_string_ostream os(sbuf);
2332 os <<
"Object leaked: ";
2335 os <<
"object allocated and stored into '"
2336 << FirstBinding->getString() <<
'\'';
2339 os <<
"allocated object";
2345 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2351 os << (isa<ObjCMethodDecl>(D) ?
" is returned from a method "
2352 :
" is returned from a function ");
2354 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
2355 os <<
"that is annotated as CF_RETURNS_NOT_RETAINED";
2356 else if (D->
hasAttr<NSReturnsNotRetainedAttr>())
2357 os <<
"that is annotated as NS_RETURNS_NOT_RETAINED";
2361 <<
"') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2362 " This violates the naming convention rules"
2363 " given in the Memory Management Guide for Cocoa";
2367 os <<
"whose name ('" << *FD
2368 <<
"') does not contain 'Copy' or 'Create'. This violates the naming"
2369 " convention rules given in the Memory Management Guide for Core"
2374 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2377 <<
"' is potentially leaked when using garbage collection. Callers "
2378 "of this method do not expect a returned object with a +1 retain "
2379 "count since they expect the object to be managed by the garbage "
2383 os <<
" is not referenced later in this execution path and has a retain "
2384 "count of +" << RV->getCount();
2386 return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
2389 CFRefLeakReport::CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
2390 bool GCEnabled,
const SummaryLogTy &Log,
2393 bool IncludeAllocationLine)
2394 : CFRefReport(D, LOpts, GCEnabled, Log, n, sym,
false) {
2408 AllocationInfo AllocI =
2411 AllocNode = AllocI.N;
2412 AllocBinding = AllocI.R;
2413 markInteresting(AllocI.InterestingMethodContext);
2419 const Stmt *AllocStmt =
nullptr;
2422 AllocStmt = Exit->getCalleeContext()->getCallSite();
2425 assert(AllocStmt &&
"Cannot find allocation statement");
2428 PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2429 AllocNode->getLocationContext());
2430 Location = AllocLocation;
2434 UniqueingLocation = AllocLocation;
2435 UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2438 Description.clear();
2439 llvm::raw_string_ostream os(Description);
2440 os <<
"Potential leak ";
2442 os <<
"(when using garbage collection) ";
2443 os <<
"of an object";
2446 os <<
" stored into '" << AllocBinding->getString() <<
'\'';
2447 if (IncludeAllocationLine) {
2453 addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2461 class RetainCountChecker
2462 :
public Checker< check::Bind,
2466 check::PostStmt<BlockExpr>,
2467 check::PostStmt<CastExpr>,
2468 check::PostStmt<ObjCArrayLiteral>,
2469 check::PostStmt<ObjCDictionaryLiteral>,
2470 check::PostStmt<ObjCBoxedExpr>,
2471 check::PostStmt<ObjCIvarRefExpr>,
2473 check::PreStmt<ReturnStmt>,
2474 check::RegionChanges,
2477 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2478 mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2479 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2480 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2481 mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2483 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2486 mutable SymbolTagMap DeadSymbolTags;
2488 mutable std::unique_ptr<RetainSummaryManager> Summaries;
2489 mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2490 mutable SummaryLogTy SummaryLog;
2491 mutable bool ShouldResetSummaryLog;
2495 mutable bool IncludeAllocationLine;
2499 : ShouldResetSummaryLog(
false),
2502 ~RetainCountChecker()
override { DeleteContainerSeconds(DeadSymbolTags); }
2534 if (ShouldResetSummaryLog)
2537 ShouldResetSummaryLog = !SummaryLog.empty();
2540 CFRefBug *getLeakWithinFunctionBug(
const LangOptions &LOpts,
2541 bool GCEnabled)
const {
2543 if (!leakWithinFunctionGC)
2544 leakWithinFunctionGC.reset(
new Leak(
this,
"Leak of object when using "
2545 "garbage collection"));
2546 return leakWithinFunctionGC.get();
2548 if (!leakWithinFunction) {
2550 leakWithinFunction.reset(
new Leak(
this,
2551 "Leak of object when not using "
2552 "garbage collection (GC) in "
2553 "dual GC/non-GC code"));
2555 leakWithinFunction.reset(
new Leak(
this,
"Leak"));
2558 return leakWithinFunction.get();
2562 CFRefBug *getLeakAtReturnBug(
const LangOptions &LOpts,
bool GCEnabled)
const {
2564 if (!leakAtReturnGC)
2565 leakAtReturnGC.reset(
new Leak(
this,
2566 "Leak of returned object when using "
2567 "garbage collection"));
2568 return leakAtReturnGC.get();
2570 if (!leakAtReturn) {
2572 leakAtReturn.reset(
new Leak(
this,
2573 "Leak of returned object when not using "
2574 "garbage collection (GC) in dual "
2577 leakAtReturn.reset(
new Leak(
this,
"Leak of returned object"));
2580 return leakAtReturn.get();
2584 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx,
2585 bool GCEnabled)
const {
2591 SummariesGC.reset(
new RetainSummaryManager(Ctx,
true, ARCEnabled));
2593 assert(SummariesGC->isARCEnabled() == ARCEnabled);
2594 return *SummariesGC;
2597 Summaries.reset(
new RetainSummaryManager(Ctx,
false, ARCEnabled));
2599 assert(Summaries->isARCEnabled() == ARCEnabled);
2609 const char *NL,
const char *Sep)
const override;
2623 void checkSummary(
const RetainSummary &Summ,
const CallEvent &Call,
2626 void processSummaryOfInlined(
const RetainSummary &Summ,
2633 bool Assumption)
const;
2690 state = state->remove<RefBindings>(sym);
2700 void RetainCountChecker::checkPostStmt(
const BlockExpr *BE,
2710 cast<BlockDataRegion>(state->getSVal(BE,
2726 for ( ; I !=
E; ++
I) {
2727 const VarRegion *VR = I.getCapturedRegion();
2731 Regions.push_back(VR);
2735 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2736 Regions.data() + Regions.size()).getState();
2740 void RetainCountChecker::checkPostStmt(
const CastExpr *CE,
2769 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2780 const Expr *Ex)
const {
2783 for (
const Stmt *Child : Ex->children()) {
2788 state = updateSymbol(state, sym, *T,
MayEscape, hasErr, C);
2790 processNonLeakError(state, Child->getSourceRange(), hasErr, sym,
C);
2811 processObjCLiterals(C, AL);
2817 processObjCLiterals(C, DL);
2820 void RetainCountChecker::checkPostStmt(
const ObjCBoxedExpr *Ex,
2826 if (
SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2836 if (
auto DerivedVal = dyn_cast<SymbolDerived>(Sym))
2837 return isa<ObjCIvarRegion>(DerivedVal->getRegion());
2838 if (
auto RegionVal = dyn_cast<SymbolRegionValue>(Sym))
2839 return isa<ObjCIvarRegion>(RegionVal->getRegion());
2850 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2862 Kind = RetEffect::CF;
2874 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2884 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2892 State =
setRefBinding(State, Sym, PlusZero.withIvarAccess());
2896 void RetainCountChecker::checkPostCall(
const CallEvent &Call,
2898 RetainSummaryManager &Summaries = getSummaryManager(C);
2899 const RetainSummary *Summ = Summaries.getSummary(Call, C.
getState());
2902 processSummaryOfInlined(*Summ, Call, C);
2905 checkSummary(*Summ, Call, C);
2922 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2923 PT->isObjCClassType()) {
2939 void RetainCountChecker::processSummaryOfInlined(
const RetainSummary &Summ,
2945 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
2956 if (MsgInvocation) {
2966 if (RE.
getKind() == RetEffect::NoRetHard) {
2978 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.
getAsRegion());
2982 QualType PointeeTy = ArgRegion->getValueType();
2986 SVal PointeeVal = State->getSVal(ArgRegion);
2994 RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
3003 llvm_unreachable(
"only for out parameters");
3009 void RetainCountChecker::checkSummary(
const RetainSummary &Summ,
3019 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3027 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3038 bool ReceiverIsTracked =
false;
3041 if (MsgInvocation) {
3044 ReceiverIsTracked =
true;
3045 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3058 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3065 if (RE.
getKind() == RetEffect::OwnedWhenTrackedReceiver) {
3066 if (ReceiverIsTracked)
3067 RE = getSummaryManager(C).getObjAllocRetEffect();
3069 RE = RetEffect::MakeNoRet();
3074 llvm_unreachable(
"Unhandled RetEffect.");
3076 case RetEffect::NoRet:
3077 case RetEffect::NoRetHard:
3081 case RetEffect::OwnedAllocatedSymbol:
3082 case RetEffect::OwnedSymbol: {
3098 case RetEffect::GCNotOwnedSymbol:
3099 case RetEffect::NotOwnedSymbol: {
3126 if (ShouldResetSummaryLog) {
3128 ShouldResetSummaryLog =
false;
3130 SummaryLog[NewNode] = &Summ;
3141 if (!IgnoreRetainMsg)
3163 V = V ^ RefVal::ErrorUseAfterRelease;
3164 hasErr = V.getKind();
3173 llvm_unreachable(
"DecRefMsg/IncRefMsg/MakeCollectable already converted");
3177 llvm_unreachable(
"Applies to pointer-to-pointer parameters, which should "
3178 "not have ref state.");
3183 V = V ^ RefVal::ErrorDeallocGC;
3184 hasErr = V.getKind();
3188 switch (V.getKind()) {
3190 llvm_unreachable(
"Invalid RefVal state for an explicit dealloc.");
3193 V = V ^ RefVal::Released;
3196 case RefVal::NotOwned:
3197 V = V ^ RefVal::ErrorDeallocNotOwned;
3198 hasErr = V.getKind();
3204 if (V.getKind() == RefVal::Owned) {
3205 V = V ^ RefVal::NotOwned;
3218 V = V.autorelease();
3226 switch (V.getKind()) {
3228 llvm_unreachable(
"Invalid RefVal state for a retain.");
3230 case RefVal::NotOwned:
3233 case RefVal::Released:
3236 V = (V ^ RefVal::Owned) + 1;
3244 switch (V.getKind()) {
3247 llvm_unreachable(
"Invalid RefVal state for a release.");
3250 assert(V.getCount() > 0);
3251 if (V.getCount() == 1) {
3253 V.getIvarAccessHistory() ==
3254 RefVal::IvarAccessHistory::AccessedDirectly)
3255 V = V ^ RefVal::NotOwned;
3257 V = V ^ RefVal::Released;
3265 case RefVal::NotOwned:
3266 if (V.getCount() > 0) {
3270 }
else if (V.getIvarAccessHistory() ==
3271 RefVal::IvarAccessHistory::AccessedDirectly) {
3276 V = V.releaseViaIvar() ^ RefVal::Released;
3278 V = V ^ RefVal::ErrorReleaseNotOwned;
3279 hasErr = V.getKind();
3283 case RefVal::Released:
3286 V = V ^ RefVal::ErrorUseAfterRelease;
3287 hasErr = V.getKind();
3307 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3315 switch (ErrorKind) {
3317 llvm_unreachable(
"Unhandled error.");
3318 case RefVal::ErrorUseAfterRelease:
3319 if (!useAfterRelease)
3320 useAfterRelease.reset(
new UseAfterRelease(
this));
3321 BT = useAfterRelease.get();
3323 case RefVal::ErrorReleaseNotOwned:
3324 if (!releaseNotOwned)
3325 releaseNotOwned.reset(
new BadRelease(
this));
3326 BT = releaseNotOwned.get();
3328 case RefVal::ErrorDeallocGC:
3330 deallocGC.reset(
new DeallocGC(
this));
3331 BT = deallocGC.get();
3333 case RefVal::ErrorDeallocNotOwned:
3334 if (!deallocNotOwned)
3335 deallocNotOwned.reset(
new DeallocNotOwned(
this));
3336 BT = deallocNotOwned.get();
3341 auto report = std::unique_ptr<BugReport>(
3343 SummaryLog, N, Sym));
3344 report->addRange(ErrorRange);
3371 StringRef FName = II->
getName();
3372 FName = FName.substr(FName.find_first_not_of(
'_'));
3375 bool canEval =
false;
3380 canEval = II->
isStr(
"NSMakeCollectable");
3398 SVal RetVal = state->getSVal(CE->
getArg(0), LCtx);
3404 state = state->BindExpr(CE, LCtx, RetVal,
false);
3411 const RefVal *Binding =
nullptr;
3416 state = state->invalidateRegions(ArgRegion, CE, C.
blockCount(), LCtx,
3432 void RetainCountChecker::checkPreStmt(
const ReturnStmt *S,
3461 switch (X.getKind()) {
3462 case RefVal::Owned: {
3463 unsigned cnt = X.getCount();
3465 X.setCount(cnt - 1);
3466 X = X ^ RefVal::ReturnedOwned;
3470 case RefVal::NotOwned: {
3471 unsigned cnt = X.getCount();
3473 X.setCount(cnt - 1);
3474 X = X ^ RefVal::ReturnedOwned;
3477 X = X ^ RefVal::ReturnedNotOwned;
3500 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3512 RetainSummaryManager &Summaries = getSummaryManager(C);
3518 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3519 RE = Summ->getRetEffect();
3520 }
else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3521 if (!isa<CXXMethodDecl>(FD)) {
3522 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3523 RE = Summ->getRetEffect();
3527 checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3530 void RetainCountChecker::checkReturnWithRetEffect(
const ReturnStmt *S,
3542 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3546 if (X.isReturnedOwned() && X.getCount() == 0) {
3547 if (RE.
getKind() != RetEffect::NoRet) {
3548 bool hasError =
false;
3555 X = X ^ RefVal::ErrorGCLeakReturned;
3562 X = X ^ RefVal::ErrorLeakReturned;
3574 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefLeakReport(
3575 *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3576 SummaryLog, N, Sym, C, IncludeAllocationLine)));
3580 }
else if (X.isReturnedNotOwned()) {
3582 if (X.getIvarAccessHistory() ==
3583 RefVal::IvarAccessHistory::AccessedDirectly) {
3587 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3591 state =
setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3594 ReturnNotOwnedTag(
this,
"ReturnNotOwnedForOwned");
3598 if (!returnNotOwnedForOwned)
3599 returnNotOwnedForOwned.reset(
new ReturnedNotOwnedForOwned(
this));
3601 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefReport(
3614 void RetainCountChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
3617 bool escapes =
true;
3628 escapes = !regionLoc->getRegion()->hasStackStorage();
3636 SVal StoredVal = state->getSVal(regionLoc->getRegion());
3637 if (StoredVal != val)
3638 escapes = (state == (state->bindLoc(*regionLoc, val)));
3644 escapes = !isa<VarRegion>(regionLoc->getRegion());
3652 const VarDecl *VD = LVR->getDecl();
3653 if (VD->
hasAttr<CleanupAttr>()) {
3666 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3672 bool Assumption)
const {
3679 RefBindingsTy B = state->get<RefBindings>();
3684 bool changed =
false;
3685 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
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>();
3881 state = handleAutoreleaseCounts(state, Pred,
nullptr, Ctx,
3882 I->first, I->second);
3894 B = state->get<RefBindings>();
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>();
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>();
3978 Out << I->first <<
" : ";
3979 I->second.print(Out);
3998 namespace objc_retain {
4003 #define createCallEffect(D, KIND)\
4004 ASTContext &Ctx = D->getASTContext();\
4005 LangOptions L = Ctx.getLangOpts();\
4006 RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
4007 const RetainSummary *S = M.get ## KIND ## Summary(D);\
4008 CallEffects CE(S->getRetEffect());\
4009 CE.Receiver = S->getReceiverEffect();\
4010 unsigned N = D->param_size();\
4011 for (unsigned i = 0; i < N; ++i) {\
4012 CE.Args.push_back(S->getArg(i));\
4025 #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.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
ParmVarDecl *const * param_const_iterator
Smart pointer class that efficiently represents Objective-C method names.
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.
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
getIdentifier - Get the identifier that names this declaration, if there is one.
FunctionType - C99 6.7.5.3 - Function Declarators.
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.
The argument acts as if has been passed to CFMakeCollectable, which transfers the object to the Garba...
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).
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.
const RegionTy * getAs() const
bool isCocoaObjectRef(QualType T)
llvm::DenseMap< Stmt *, Stmt * > MapTy
static Selector getKeywordSelector(ASTContext &Ctx, va_list argp)
static RetEffect MakeNoRet()
VarDecl - An instance of this class is created to represent a variable declaration or definition...
referenced_vars_iterator referenced_vars_begin() const
bool hasCaptures() const
hasCaptures - True if this block (or its nested blocks) captures anything of local storage from its e...
The argument is a pointer to a retain-counted object; on exit, the new value of the pointer is a +1 v...
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...
const MemRegion * getBaseRegion() const
void addRange(SourceRange R)
ParmVarDecl - Represents a parameter to a function.
bool isObjCRetainableType() const
const bool wasInlined
If we are post visiting a call, this flag will be set if the call was inlined.
const char *const MemoryCoreFoundationObjectiveC
referenced_vars_iterator referenced_vars_end() const
unsigned getNumParams() 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...
const ObjCInterfaceDecl * getReceiverInterface() const
Get the interface for the receiver.
One of these records is kept for each identifier that is lexed.
static RetEffect MakeNoRetHard()
MemRegionManager & getRegionManager()
class LLVM_ALIGNAS(8) DependentTemplateSpecializationType const IdentifierInfo * Name
Represents a template specialization type whose template cannot be resolved, e.g. ...
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
This class provides a convenience implementation for clone() using the Curiously-Recurring Template P...
The argument is treated as if an -autorelease message had been sent to the referenced object...
AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getOriginExpr() const
Returns the expression whose value will be the result of this call.
SymbolRef getAsLocSymbol(bool IncludeBaseRegions=false) const
If this SVal is a location and wraps a symbol, return that SymbolRef.
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
getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a CodeTextRegion wrapping a FunctionDecl...
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]];.
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)
BlockDataRegion - A region that represents a block instance.
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.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
static void Profile(const ArgEffect X, FoldingSetNodeID &ID)
ProgramStateManager & getStateManager()
The argument has its reference count increased by 1.
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
QualType getReturnType() const
const TemplateArgument & getArg(unsigned Idx) const
Retrieve a specific template argument as a type.
const Stmt * getCallSite() const
bool isParentOf(const LocationContext *LC) const
dead_iterator dead_begin() const
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)
detail::InMemoryDirectory::const_iterator I
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
ArgEffect
An ArgEffect summarizes the retain count behavior on an argument or receiver to a function or method...
const ParmVarDecl *const * param_const_iterator
Represents a prototype with parameter type info, e.g.
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 MemRegion * StripCasts(bool StripBaseCasts=true) const
Represents a point when we finish the call exit sequence (for inlined call).
ID
Defines the set of possible language-specific address spaces.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceDecl *PrevDecl=nullptr) const
getObjCInterfaceType - Return the unique reference to the type for the specified ObjC interface decl...
SymbolicRegion - A special, "non-concrete" region.
bool inTopFrame() const
Return true if the current LocationContext has no caller context.
Expr - This represents one expression.
const ProgramStateRef & getState() const
Defines the clang::LangOptions interface.
Indicates that the tracked object is a CF object.
StringRef getName() const
Return the actual identifier string.
const ProgramStateRef & getState() const
unsigned getNumArgs() const
SourceRange getReceiverRange() const
Source range of the receiver.
BlockExpr - Adaptor class for mixing a BlockDecl with expressions.
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.
ObjCDictionaryLiteral - AST node to represent objective-c dictionary literals; as in:"name" : NSUserN...
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)
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.
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)
Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...
param_const_iterator param_end() const
void emitReport(std::unique_ptr< BugReport > R)
Emit the diagnostics report.
BugReporter is a utility class for generating PathDiagnostics for analysis.
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.
ConstExprIterator const_arg_iterator
The argument has its reference count increased by 1.
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 TemplateArgument * iterator
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...
const StackFrameContext * getCurrentStackFrame() const
ProgramPoints can be "tagged" as representing points specific to a given analysis entity...
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
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
Selector getSelector() const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
bool isPropertyAccessor() const
dead_iterator dead_end() const
#define va_start(ap, param)
std::string getAsString() const
Derive the full selector name (e.g.
const Decl * getDecl() const
A class responsible for cleaning up unused symbols.
QualType getReturnType() const
const IdentifierInfo * getIdentifier() const
const StackFrameContext * getStackFrame() const
ObjCBoxedExpr - used for generalized expression boxing.
const BlockDecl * getBlockDecl() const
const ObjCMethodDecl * getDecl() const override
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
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
All typestate tracking of the object ceases.
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
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.
__builtin_va_list va_list
QualType getObjCObjectPointerType(QualType OIT) const
Return a ObjCObjectPointerType type for the given ObjCObjectType.
Selector getSelector() const
detail::InMemoryDirectory::const_iterator E
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
getNumArgs - Return the number of actual arguments to this call.
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()
RetEffect summarizes a call's retain/release behavior with respect to its return value.
param_iterator param_end()
static ArgEffect getStopTrackingHardEquivalent(ArgEffect E)
virtual void dumpToStream(raw_ostream &os) const
Represents a pointer to an Objective C object.
QualType getResultType() const
Returns the result type, adjusted for references.
const T * getAs() const
Member-template getAs<specific type>'.
#define createCallEffect(D, KIND)
Performs the combined functionality of DecRefMsg and StopTrackingHard.
ProgramStateManager & getStateManager()
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.
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).
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)
Create a location corresponding to the next valid ExplodedNode as end of path location.
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
bool isObjCGCEnabled() const
SValBuilder & getSValBuilder()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
A SourceLocation and its associated SourceManager.
ObjCInterfaceDecl * getSuperClass() const
static Decl::Kind getKind(const Decl *D)
virtual const ExplodedNode * getOriginalNode(const ExplodedNode *N)=0
All typestate tracking of the object ceases.
void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler &F)
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...
ParentMap & getParentMap()
A trivial tuple used to represent a source range.
Tag that can use a checker name as a message provider (see SimpleProgramPointTag).
This class provides an interface through which checkers can create individual bug reports...
bool hasNonZeroCallbackArg() const
Returns true if any of the arguments appear to represent callbacks.
static unsigned getHashValue(const ObjCSummaryKey &V)
bool isNull() const
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)
GetReturnType - Used to get the return type of a message expression or function call with the intenti...
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