34 #include "llvm/ADT/DenseMap.h"
35 #include "llvm/ADT/FoldingSet.h"
36 #include "llvm/ADT/ImmutableList.h"
37 #include "llvm/ADT/ImmutableMap.h"
38 #include "llvm/ADT/STLExtras.h"
39 #include "llvm/ADT/SmallString.h"
40 #include "llvm/ADT/StringExtras.h"
44 using namespace clang;
46 using namespace objc_retain;
47 using llvm::StrInStrNoCase;
56 ID.AddInteger((
unsigned) X);
61 ID.AddInteger((
unsigned) X.
getKind());
102 enum class IvarAccessHistory {
105 ReleasedAfterDirectAccess
119 unsigned RawKind : 5;
124 unsigned RawObjectKind : 2;
135 unsigned RawIvarAccessHistory : 2;
138 IvarAccessHistory IvarAccess)
139 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
140 RawObjectKind(static_cast<unsigned>(o)),
141 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
142 assert(
getKind() == k &&
"not enough bits for the kind");
143 assert(getObjKind() == o &&
"not enough bits for the object kind");
144 assert(getIvarAccessHistory() == IvarAccess &&
"not enough bits");
154 unsigned getCount()
const {
return Cnt; }
155 unsigned getAutoreleaseCount()
const {
return ACnt; }
156 unsigned getCombinedCounts()
const {
return Cnt + ACnt; }
161 void setCount(
unsigned i) {
164 void setAutoreleaseCount(
unsigned i) {
168 QualType getType()
const {
return T; }
175 IvarAccessHistory getIvarAccessHistory()
const {
176 return static_cast<IvarAccessHistory
>(RawIvarAccessHistory);
179 bool isOwned()
const {
183 bool isNotOwned()
const {
187 bool isReturnedOwned()
const {
188 return getKind() == ReturnedOwned;
191 bool isReturnedNotOwned()
const {
192 return getKind() == ReturnedNotOwned;
200 unsigned Count = 1) {
209 unsigned Count = 0) {
213 RefVal operator-(
size_t i)
const {
214 return RefVal(
getKind(), getObjKind(), getCount() - i,
215 getAutoreleaseCount(), getType(), getIvarAccessHistory());
218 RefVal operator+(
size_t i)
const {
219 return RefVal(
getKind(), getObjKind(), getCount() + i,
220 getAutoreleaseCount(), getType(), getIvarAccessHistory());
223 RefVal operator^(
Kind k)
const {
224 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
225 getType(), getIvarAccessHistory());
228 RefVal autorelease()
const {
229 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
230 getType(), getIvarAccessHistory());
233 RefVal withIvarAccess()
const {
235 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
236 getType(), IvarAccessHistory::AccessedDirectly);
239 RefVal releaseViaIvar()
const {
240 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
241 return RefVal(
getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
242 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
247 bool hasSameState(
const RefVal &
X)
const {
248 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
249 getIvarAccessHistory() == X.getIvarAccessHistory();
253 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
256 void Profile(llvm::FoldingSetNodeID&
ID)
const {
258 ID.AddInteger(RawKind);
261 ID.AddInteger(RawObjectKind);
262 ID.AddInteger(RawIvarAccessHistory);
265 void print(raw_ostream &Out)
const;
268 void RefVal::print(raw_ostream &Out)
const {
270 Out <<
"Tracked " << T.getAsString() <<
'/';
273 default: llvm_unreachable(
"Invalid RefVal kind");
276 unsigned cnt = getCount();
277 if (cnt) Out <<
" (+ " << cnt <<
")";
283 unsigned cnt = getCount();
284 if (cnt) Out <<
" (+ " << cnt <<
")";
288 case ReturnedOwned: {
289 Out <<
"ReturnedOwned";
290 unsigned cnt = getCount();
291 if (cnt) Out <<
" (+ " << cnt <<
")";
295 case ReturnedNotOwned: {
296 Out <<
"ReturnedNotOwned";
297 unsigned cnt = getCount();
298 if (cnt) Out <<
" (+ " << cnt <<
")";
307 Out <<
"-dealloc (GC)";
310 case ErrorDeallocNotOwned:
311 Out <<
"-dealloc (not-owned)";
318 case ErrorLeakReturned:
319 Out <<
"Leaked (Bad naming)";
322 case ErrorGCLeakReturned:
323 Out <<
"Leaked (GC-ed at return)";
326 case ErrorUseAfterRelease:
327 Out <<
"Use-After-Release [ERROR]";
330 case ErrorReleaseNotOwned:
331 Out <<
"Release of Not-Owned [ERROR]";
334 case RefVal::ErrorOverAutorelease:
335 Out <<
"Over-autoreleased";
338 case RefVal::ErrorReturnedNotOwned:
339 Out <<
"Non-owned object returned instead of owned";
343 switch (getIvarAccessHistory()) {
346 case IvarAccessHistory::AccessedDirectly:
347 Out <<
" [direct ivar access]";
349 case IvarAccessHistory::ReleasedAfterDirectAccess:
350 Out <<
" [released after direct ivar access]";
354 Out <<
" [autorelease -" << ACnt <<
']';
367 return State->get<RefBindings>(Sym);
372 return State->set<RefBindings>(Sym, Val);
376 return State->remove<RefBindings>(Sym);
384 class RetainSummary {
405 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), Ret(R) {}
410 if (
const ArgEffect *AE = Args.lookup(idx))
413 return DefaultArgEffect;
416 void addArg(ArgEffects::Factory &af,
unsigned idx,
ArgEffect e) {
417 Args = af.add(Args, idx, e);
422 DefaultArgEffect =
E;
426 RetEffect getRetEffect()
const {
return Ret; }
433 void setReceiverEffect(
ArgEffect e) { Receiver = e; }
437 ArgEffect getReceiverEffect()
const {
return Receiver; }
442 bool operator==(
const RetainSummary &Other)
const {
443 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
444 Receiver == Other.Receiver && Ret == Other.Ret;
448 void Profile(llvm::FoldingSetNodeID&
ID)
const {
450 ID.Add(DefaultArgEffect);
456 bool isSimple()
const {
457 return Args.isEmpty();
461 ArgEffects getArgEffects()
const {
return Args; }
462 ArgEffect getDefaultArgEffect()
const {
return DefaultArgEffect; }
464 friend class RetainSummaryManager;
473 class ObjCSummaryKey {
484 : II(nullptr),
S(s) {}
487 Selector getSelector()
const {
return S; }
504 typedef std::pair<IdentifierInfo*, Selector> PairTy;
509 static bool isEqual(
const ObjCSummaryKey& LHS,
const ObjCSummaryKey& RHS) {
510 return LHS.getIdentifier() == RHS.getIdentifier() &&
511 LHS.getSelector() == RHS.getSelector();
518 class ObjCSummaryCache {
519 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *>
MapTy;
522 ObjCSummaryCache() {}
527 ObjCSummaryKey K(D, S);
542 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
551 const RetainSummary *Summ = I->second;
562 I = M.find(ObjCSummaryKey(S));
564 return I == M.end() ?
nullptr : I->second;
567 const RetainSummary *& operator[](ObjCSummaryKey K) {
571 const RetainSummary *& operator[](
Selector S) {
572 return M[ ObjCSummaryKey(S) ];
582 class RetainSummaryManager {
588 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
591 typedef ObjCSummaryCache ObjCMethodSummariesTy;
593 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
603 const bool GCEnabled;
606 const bool ARCEnabled;
609 FuncSummariesTy FuncSummaries;
613 ObjCMethodSummariesTy ObjCClassMethodSummaries;
616 ObjCMethodSummariesTy ObjCMethodSummaries;
620 llvm::BumpPtrAllocator BPAlloc;
623 ArgEffects::Factory AF;
638 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
648 enum UnaryFuncKind { cfretain, cfrelease, cfautorelease, cfmakecollectable };
650 const RetainSummary *getUnarySummary(
const FunctionType* FT,
653 const RetainSummary *getCFSummaryCreateRule(
const FunctionDecl *FD);
654 const RetainSummary *getCFSummaryGetRule(
const FunctionDecl *FD);
655 const RetainSummary *getCFCreateGetRuleSummary(
const FunctionDecl *FD);
657 const RetainSummary *getPersistentSummary(
const RetainSummary &OldSumm);
659 const RetainSummary *getPersistentSummary(
RetEffect RetEff,
662 RetainSummary Summ(getArgEffects(), RetEff, DefaultEff, ReceiverEff);
663 return getPersistentSummary(Summ);
666 const RetainSummary *getDoNothingSummary() {
670 const RetainSummary *getDefaultSummary() {
675 const RetainSummary *getPersistentStopSummary() {
680 void InitializeClassMethodSummaries();
681 void InitializeMethodSummaries();
683 void addNSObjectClsMethSummary(
Selector S,
const RetainSummary *Summ) {
684 ObjCClassMethodSummaries[
S] = Summ;
687 void addNSObjectMethSummary(
Selector S,
const RetainSummary *Summ) {
688 ObjCMethodSummaries[
S] = Summ;
691 void addClassMethSummary(
const char* Cls,
const char* name,
692 const RetainSummary *Summ,
bool isNullary =
true) {
696 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
699 void addInstMethSummary(
const char* Cls,
const char* nullaryName,
700 const RetainSummary *Summ) {
703 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ;
706 void addMethodSummary(
IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
707 const RetainSummary *Summ,
va_list argp) {
709 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
712 void addInstMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
715 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp);
719 void addClsMethSummary(
const char* Cls,
const RetainSummary * Summ, ...) {
722 addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp);
726 void addClsMethSummary(
IdentifierInfo *II,
const RetainSummary * Summ, ...) {
729 addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp);
735 RetainSummaryManager(
ASTContext &ctx,
bool gcenabled,
bool usesARC)
737 GCEnabled(gcenabled),
739 AF(BPAlloc), ScratchArgs(AF.getEmptyMap()),
740 ObjCAllocRetE(gcenabled
744 ObjCInitRetE(gcenabled
747 :
RetEffect::MakeOwnedWhenTrackedReceiver())) {
748 InitializeClassMethodSummaries();
749 InitializeMethodSummaries();
752 const RetainSummary *getSummary(
const CallEvent &Call,
755 const RetainSummary *getFunctionSummary(
const FunctionDecl *FD);
760 ObjCMethodSummariesTy &CachedSummaries);
762 const RetainSummary *getInstanceMethodSummary(
const ObjCMethodCall &M,
765 const RetainSummary *getClassMethodSummary(
const ObjCMethodCall &M) {
770 M.getResultType(), ObjCClassMethodSummaries);
780 ObjCMethodSummariesTy *CachedSummaries;
782 CachedSummaries = &ObjCMethodSummaries;
784 CachedSummaries = &ObjCClassMethodSummaries;
786 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
789 const RetainSummary *getStandardMethodSummary(
const ObjCMethodDecl *MD,
796 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
799 void updateSummaryFromAnnotations(
const RetainSummary *&Summ,
802 void updateSummaryForCall(
const RetainSummary *&Summ,
805 bool isGCEnabled()
const {
return GCEnabled; }
807 bool isARCEnabled()
const {
return ARCEnabled; }
809 bool isARCorGCEnabled()
const {
return GCEnabled || ARCEnabled; }
811 RetEffect getObjAllocRetEffect()
const {
return ObjCAllocRetE; }
813 friend class RetainSummaryTemplate;
820 class RetainSummaryTemplate {
821 RetainSummaryManager &Manager;
822 const RetainSummary *&RealSummary;
823 RetainSummary ScratchSummary;
826 RetainSummaryTemplate(
const RetainSummary *&real, RetainSummaryManager &mgr)
827 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(
false) {}
829 ~RetainSummaryTemplate() {
831 RealSummary = Manager.getPersistentSummary(ScratchSummary);
836 return ScratchSummary;
839 RetainSummary *operator->() {
841 return &ScratchSummary;
851 ArgEffects RetainSummaryManager::getArgEffects() {
853 ScratchArgs = AF.getEmptyMap();
857 const RetainSummary *
858 RetainSummaryManager::getPersistentSummary(
const RetainSummary &OldSumm) {
860 if (OldSumm.isSimple()) {
861 llvm::FoldingSetNodeID
ID;
865 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
868 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
869 new (N) CachedSummaryNode(OldSumm);
870 SimpleSummaries.InsertNode(N, Pos);
873 return &N->getValue();
876 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
877 new (Summ) RetainSummary(OldSumm);
886 return FName.endswith(
"Retain");
890 return FName.endswith(
"Release");
894 return FName.endswith(
"Autorelease");
900 return FName.find(
"MakeCollectable") != StringRef::npos;
927 llvm_unreachable(
"Unknown ArgEffect kind");
930 void RetainSummaryManager::updateSummaryForCall(
const RetainSummary *&S,
938 ArgEffects CustomArgEffects = S->getArgEffects();
940 E = CustomArgEffects.end();
943 if (Translated != DefEffect)
944 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
956 if (
Name->
isStr(
"CGBitmapContextCreateWithData"))
957 RE = S->getRetEffect();
961 S = getPersistentSummary(RE, RecEffect, DefEffect);
977 if (MC->getMethodFamily() ==
OMF_init && MC->isReceiverSelfOrSuper()) {
981 const Expr *ME = MC->getOriginExpr();
985 RetainSummaryTemplate ModifiableSummaryTemplate(S, *
this);
986 ModifiableSummaryTemplate->setReceiverEffect(
DoNothing);
993 const RetainSummary *
994 RetainSummaryManager::getSummary(
const CallEvent &Call,
996 const RetainSummary *Summ;
999 Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
1008 return getPersistentStopSummary();
1012 Summ = getInstanceMethodSummary(Msg, State);
1014 Summ = getClassMethodSummary(Msg);
1019 updateSummaryForCall(Summ, Call);
1021 assert(Summ &&
"Unknown call type?");
1025 const RetainSummary *
1026 RetainSummaryManager::getFunctionSummary(
const FunctionDecl *FD) {
1029 return getDefaultSummary();
1033 if (I != FuncSummaries.end())
1037 const RetainSummary *S =
nullptr;
1038 bool AllowAnnotations =
true;
1042 if (FD->isImplicit()) {
1043 S = getPersistentStopSummary();
1054 StringRef FName = II->
getName();
1058 FName = FName.substr(FName.find_first_not_of(
'_'));
1065 assert(ScratchArgs.isEmpty());
1067 if (FName ==
"pthread_create" || FName ==
"pthread_setspecific") {
1070 S = getPersistentStopSummary();
1071 }
else if (FName ==
"NSMakeCollectable") {
1074 ? getUnarySummary(FT, cfmakecollectable)
1075 : getPersistentStopSummary();
1078 AllowAnnotations =
false;
1079 }
else if (FName ==
"CFPlugInInstanceCreate") {
1081 }
else if (FName ==
"IOBSDNameMatching" ||
1082 FName ==
"IOServiceMatching" ||
1083 FName ==
"IOServiceNameMatching" ||
1084 FName ==
"IORegistryEntrySearchCFProperty" ||
1085 FName ==
"IORegistryEntryIDMatching" ||
1086 FName ==
"IOOpenFirmwarePathMatching") {
1091 }
else if (FName ==
"IOServiceGetMatchingService" ||
1092 FName ==
"IOServiceGetMatchingServices") {
1096 ScratchArgs = AF.add(ScratchArgs, 1,
DecRef);
1098 }
else if (FName ==
"IOServiceAddNotification" ||
1099 FName ==
"IOServiceAddMatchingNotification") {
1102 ScratchArgs = AF.add(ScratchArgs, 2,
DecRef);
1104 }
else if (FName ==
"CVPixelBufferCreateWithBytes") {
1113 }
else if (FName ==
"CGBitmapContextCreateWithData") {
1121 }
else if (FName ==
"CVPixelBufferCreateWithPlanarBytes") {
1129 }
else if (FName ==
"dispatch_set_context" ||
1130 FName ==
"xpc_connection_set_context") {
1139 }
else if (FName.startswith(
"NSLog")) {
1140 S = getDoNothingSummary();
1141 }
else if (FName.startswith(
"NS") &&
1142 (FName.find(
"Insert") != StringRef::npos)) {
1158 S = getUnarySummary(FT, cfretain);
1160 S = getUnarySummary(FT, cfautorelease);
1163 AllowAnnotations =
false;
1165 S = getUnarySummary(FT, cfmakecollectable);
1166 AllowAnnotations =
false;
1168 S = getCFCreateGetRuleSummary(FD);
1177 S = getUnarySummary(FT, cfretain);
1179 S = getCFCreateGetRuleSummary(FD);
1188 S = getCFCreateGetRuleSummary(FD);
1192 if (FD->hasAttr<CFAuditedTransferAttr>()) {
1193 S = getCFCreateGetRuleSummary(FD);
1202 if (FName[0] ==
'C' && (FName[1] ==
'F' || FName[1] ==
'G')) {
1204 FName = FName.substr(FName.startswith(
"CGCF") ? 4 : 2);
1207 S = getUnarySummary(FT, cfrelease);
1209 assert (ScratchArgs.isEmpty());
1225 ArgEffect E = (StrInStrNoCase(FName,
"InsertValue") != StringRef::npos||
1226 StrInStrNoCase(FName,
"AddValue") != StringRef::npos ||
1227 StrInStrNoCase(FName,
"SetValue") != StringRef::npos ||
1228 StrInStrNoCase(FName,
"AppendValue") != StringRef::npos||
1229 StrInStrNoCase(FName,
"SetAttribute") != StringRef::npos)
1240 S = getDefaultSummary();
1243 if (AllowAnnotations)
1244 updateSummaryFromAnnotations(S, FD);
1246 FuncSummaries[FD] =
S;
1250 const RetainSummary *
1251 RetainSummaryManager::getCFCreateGetRuleSummary(
const FunctionDecl *FD) {
1253 return getCFSummaryCreateRule(FD);
1255 return getCFSummaryGetRule(FD);
1258 const RetainSummary *
1259 RetainSummaryManager::getUnarySummary(
const FunctionType* FT,
1260 UnaryFuncKind func) {
1266 return getPersistentStopSummary();
1268 assert (ScratchArgs.isEmpty());
1272 case cfretain: Effect =
IncRef;
break;
1273 case cfrelease: Effect =
DecRef;
break;
1278 ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1282 const RetainSummary *
1283 RetainSummaryManager::getCFSummaryCreateRule(
const FunctionDecl *FD) {
1284 assert (ScratchArgs.isEmpty());
1286 return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF,
true));
1289 const RetainSummary *
1290 RetainSummaryManager::getCFSummaryGetRule(
const FunctionDecl *FD) {
1291 assert (ScratchArgs.isEmpty());
1292 return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1301 RetainSummaryManager::getRetEffectFromAnnotations(
QualType RetTy,
1304 if (D->hasAttr<NSReturnsRetainedAttr>())
1305 return ObjCAllocRetE;
1307 if (D->hasAttr<NSReturnsNotRetainedAttr>() ||
1308 D->hasAttr<NSReturnsAutoreleasedAttr>())
1315 if (D->hasAttr<CFReturnsRetainedAttr>())
1316 return RetEffect::MakeOwned(RetEffect::CF,
true);
1318 if (D->hasAttr<CFReturnsNotRetainedAttr>())
1319 return RetEffect::MakeNotOwned(RetEffect::CF);
1325 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1330 assert(Summ &&
"Must have a summary to add annotations to.");
1331 RetainSummaryTemplate Template(Summ, *
this);
1334 unsigned parm_idx = 0;
1336 pe = FD->
param_end(); pi != pe; ++pi, ++parm_idx) {
1338 if (pd->hasAttr<NSConsumedAttr>())
1339 Template->addArg(AF, parm_idx,
DecRefMsg);
1340 else if (pd->hasAttr<CFConsumedAttr>())
1341 Template->addArg(AF, parm_idx,
DecRef);
1342 else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
1347 }
else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
1357 Template->setRetEffect(*RetE);
1361 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1366 assert(Summ &&
"Must have a valid summary to add annotations to");
1367 RetainSummaryTemplate Template(Summ, *
this);
1370 if (MD->hasAttr<NSConsumesSelfAttr>())
1374 unsigned parm_idx = 0;
1377 pi != pe; ++pi, ++parm_idx) {
1379 if (pd->hasAttr<NSConsumedAttr>())
1380 Template->addArg(AF, parm_idx,
DecRefMsg);
1381 else if (pd->hasAttr<CFConsumedAttr>()) {
1382 Template->addArg(AF, parm_idx,
DecRef);
1383 }
else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
1388 }
else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
1398 Template->setRetEffect(*RetE);
1401 const RetainSummary *
1402 RetainSummaryManager::getStandardMethodSummary(
const ObjCMethodDecl *MD,
1406 RetEffect ResultEff = RetEffect::MakeNoRet();
1429 ResultEff = RetEffect::MakeOwned(RetEffect::CF,
true);
1432 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1436 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1441 ResultEff = ObjCInitRetE;
1449 ResultEff = ObjCAllocRetE;
1451 ResultEff = RetEffect::MakeOwned(RetEffect::CF,
true);
1479 for (
unsigned i = 0, e = S.
getNumArgs(); i != e; ++i) {
1481 if (Slot.substr(Slot.size() - 8).equals_lower(
"delegate")) {
1482 if (ResultEff == ObjCInitRetE)
1483 ResultEff = RetEffect::MakeNoRetHard();
1490 if (ScratchArgs.isEmpty() && ReceiverEff ==
DoNothing &&
1491 ResultEff.
getKind() == RetEffect::NoRet)
1492 return getDefaultSummary();
1494 return getPersistentSummary(ResultEff, ReceiverEff,
MayEscape);
1497 const RetainSummary *
1498 RetainSummaryManager::getInstanceMethodSummary(
const ObjCMethodCall &Msg,
1512 ReceiverClass = PT->getInterfaceDecl();
1524 if (!Method && ReceiverClass)
1527 return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1528 ObjCMethodSummaries);
1531 const RetainSummary *
1534 ObjCMethodSummariesTy &CachedSummaries) {
1537 const RetainSummary *Summ = CachedSummaries.find(ID, S);
1540 Summ = getStandardMethodSummary(MD, S, RetTy);
1543 updateSummaryFromAnnotations(Summ, MD);
1546 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1552 void RetainSummaryManager::InitializeClassMethodSummaries() {
1553 assert(ScratchArgs.isEmpty());
1555 addClassMethSummary(
"NSAssertionHandler",
"currentHandler",
1559 ScratchArgs = AF.add(ScratchArgs, 0,
Autorelease);
1560 addClassMethSummary(
"NSAutoreleasePool",
"addObject",
1561 getPersistentSummary(RetEffect::MakeNoRet(),
1565 void RetainSummaryManager::InitializeMethodSummaries() {
1567 assert (ScratchArgs.isEmpty());
1571 const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE,
DecRefMsg);
1580 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1581 const RetainSummary *CFAllocSumm =
1582 getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF,
true));
1585 RetEffect NoRet = RetEffect::MakeNoRet();
1586 const RetainSummary *Summ = getPersistentSummary(NoRet,
IncRefMsg);
1590 Summ = getPersistentSummary(NoRet,
DecRefMsg);
1594 Summ = getPersistentSummary(NoRet,
Dealloc);
1607 const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1611 addClassMethSummary(
"NSWindow",
"alloc", NoTrackYet);
1617 addClassMethSummary(
"NSPanel",
"alloc", NoTrackYet);
1622 addClassMethSummary(
"NSNull",
"null", NoTrackYet);
1626 addClassMethSummary(
"NSAutoreleasePool",
"alloc", NoTrackYet);
1627 addClassMethSummary(
"NSAutoreleasePool",
"allocWithZone", NoTrackYet,
false);
1628 addClassMethSummary(
"NSAutoreleasePool",
"new", NoTrackYet);
1631 addInstMethSummary(
"QCRenderer", AllocSumm,
1632 "createSnapshotImageOfType",
nullptr);
1633 addInstMethSummary(
"QCView", AllocSumm,
1634 "createSnapshotImageOfType",
nullptr);
1639 addInstMethSummary(
"CIContext", CFAllocSumm,
1640 "createCGImage",
"fromRect",
nullptr);
1641 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect",
1642 "format",
"colorSpace",
nullptr);
1643 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGLayerWithSize",
"info",
1651 typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1658 class CFRefBug :
public BugType {
1660 CFRefBug(
const CheckerBase *checker, StringRef name)
1666 virtual const char *getDescription()
const = 0;
1668 virtual bool isLeak()
const {
return false; }
1671 class UseAfterRelease :
public CFRefBug {
1674 : CFRefBug(checker,
"Use-after-release") {}
1676 const char *getDescription()
const override {
1677 return "Reference-counted object is used after it is released";
1681 class BadRelease :
public CFRefBug {
1683 BadRelease(
const CheckerBase *checker) : CFRefBug(checker,
"Bad release") {}
1685 const char *getDescription()
const override {
1686 return "Incorrect decrement of the reference count of an object that is "
1687 "not owned at this point by the caller";
1691 class DeallocGC :
public CFRefBug {
1694 : CFRefBug(checker,
"-dealloc called while using garbage collection") {}
1696 const char *getDescription()
const override {
1697 return "-dealloc called while using garbage collection";
1701 class DeallocNotOwned :
public CFRefBug {
1704 : CFRefBug(checker,
"-dealloc sent to non-exclusively owned object") {}
1706 const char *getDescription()
const override {
1707 return "-dealloc sent to object that may be referenced elsewhere";
1711 class OverAutorelease :
public CFRefBug {
1714 : CFRefBug(checker,
"Object autoreleased too many times") {}
1716 const char *getDescription()
const override {
1717 return "Object autoreleased too many times";
1721 class ReturnedNotOwnedForOwned :
public CFRefBug {
1723 ReturnedNotOwnedForOwned(
const CheckerBase *checker)
1724 : CFRefBug(checker,
"Method should return an owned object") {}
1726 const char *getDescription()
const override {
1727 return "Object with a +0 retain count returned to caller where a +1 "
1728 "(owning) retain count is expected";
1732 class Leak :
public CFRefBug {
1734 Leak(
const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
1736 setSuppressOnSink(
true);
1739 const char *getDescription()
const override {
return ""; }
1741 bool isLeak()
const override {
return true; }
1751 const SummaryLogTy &SummaryLog;
1755 CFRefReportVisitor(
SymbolRef sym,
bool gcEnabled,
const SummaryLogTy &
log)
1756 : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1758 void Profile(llvm::FoldingSetNodeID &ID)
const override {
1774 class CFRefLeakReportVisitor :
public CFRefReportVisitor {
1776 CFRefLeakReportVisitor(
SymbolRef sym,
bool GCEnabled,
1777 const SummaryLogTy &
log)
1778 : CFRefReportVisitor(sym, GCEnabled, log) {}
1784 std::unique_ptr<BugReporterVisitor> clone()
const override {
1790 return llvm::make_unique<CFRefLeakReportVisitor>(*this);
1795 void addGCModeDescription(
const LangOptions &LOpts,
bool GCEnabled);
1798 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1800 bool registerVisitor =
true)
1802 if (registerVisitor)
1803 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1804 addGCModeDescription(LOpts, GCEnabled);
1807 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1810 :
BugReport(D, D.getDescription(), endText, n) {
1811 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1812 addGCModeDescription(LOpts, GCEnabled);
1815 llvm::iterator_range<ranges_iterator> getRanges()
override {
1816 const CFRefBug& BugTy =
static_cast<CFRefBug&
>(getBugType());
1817 if (!BugTy.isLeak())
1819 return llvm::make_range(ranges_iterator(), ranges_iterator());
1823 class CFRefLeakReport :
public CFRefReport {
1826 CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1829 bool IncludeAllocationLine);
1832 assert(Location.isValid());
1838 void CFRefReport::addGCModeDescription(
const LangOptions &LOpts,
1840 const char *GCModeDescription =
nullptr;
1842 switch (LOpts.getGC()) {
1845 GCModeDescription =
"Code is compiled to only use garbage collection";
1850 GCModeDescription =
"Code is compiled to use reference counts";
1855 GCModeDescription =
"Code is compiled to use either garbage collection "
1856 "(GC) or reference counts (non-GC). The bug occurs "
1860 GCModeDescription =
"Code is compiled to use either garbage collection "
1861 "(GC) or reference counts (non-GC). The bug occurs "
1867 assert(GCModeDescription &&
"invalid/unknown GC mode");
1868 addExtraText(GCModeDescription);
1873 return isa<IntegerLiteral>(
E) ||
1874 isa<CharacterLiteral>(E) ||
1875 isa<FloatingLiteral>(
E) ||
1876 isa<ObjCBoolLiteralExpr>(E) ||
1877 isa<CXXBoolLiteralExpr>(
E);
1883 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->
getDecl());
1905 if (!CurrT)
return nullptr;
1907 const RefVal &CurrV = *CurrT;
1913 llvm::raw_string_ostream os(sbuf);
1920 if (isa<ObjCIvarRefExpr>(S) &&
1925 if (isa<ObjCArrayLiteral>(S)) {
1926 os <<
"NSArray literal is an object with a +0 retain count";
1928 else if (isa<ObjCDictionaryLiteral>(S)) {
1929 os <<
"NSDictionary literal is an object with a +0 retain count";
1931 else if (
const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1933 os <<
"NSNumber literal is an object with a +0 retain count";
1942 os << *BoxClass <<
" b";
1946 os <<
"oxed expression produces an object with a +0 retain count";
1949 else if (isa<ObjCIvarRefExpr>(S)) {
1950 os <<
"Object loaded from instance variable";
1953 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1955 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
1957 os <<
"Call to function '" << *FD <<
'\'';
1959 os <<
"function call";
1962 assert(isa<ObjCMessageExpr>(S));
1967 switch (Call->getMessageKind()) {
1980 if (CurrV.getObjKind() == RetEffect::CF) {
1981 os <<
" returns a Core Foundation object with a ";
1985 os <<
" returns an Objective-C object with a ";
1988 if (CurrV.isOwned()) {
1989 os <<
"+1 retain count";
1992 assert(CurrV.getObjKind() == RetEffect::CF);
1994 "Core Foundation objects are not automatically garbage collected.";
1998 assert (CurrV.isNotOwned());
1999 os <<
"+0 retain count";
2013 if (
const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
2018 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2024 AI!=AE; ++AI, ++i) {
2028 if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
2032 AEffects.push_back(Summ->getArg(i));
2036 if (
const Expr *receiver = ME->getInstanceReceiver())
2037 if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
2038 .getAsLocSymbol() == Sym) {
2040 AEffects.push_back(Summ->getReceiverEffect());
2047 RefVal PrevV = *PrevT;
2050 if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(),
Dealloc) !=
2053 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2056 if (CurrV.getKind() == RefVal::Released) {
2057 assert(CurrV.getCombinedCounts() == 0);
2058 os <<
"Object released by directly sending the '-dealloc' message";
2069 CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2074 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2076 os <<
"In GC mode a call to '" << *FD
2077 <<
"' decrements an object's retain count and registers the "
2078 "object with the garbage collector. ";
2080 if (CurrV.getKind() == RefVal::Released) {
2081 assert(CurrV.getCount() == 0);
2082 os <<
"Since it now has a 0 retain count the object can be "
2083 "automatically collected by the garbage collector.";
2086 os <<
"An object must have a 0 retain count to be garbage collected. "
2087 "After this call its retain count is +" << CurrV.getCount()
2091 os <<
"When GC is not enabled a call to '" << *FD
2092 <<
"' has no effect on its argument.";
2099 if (!PrevV.hasSameState(CurrV))
2100 switch (CurrV.getKind()) {
2102 case RefVal::NotOwned:
2103 if (PrevV.getCount() == CurrV.getCount()) {
2105 if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2108 assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2109 os <<
"Object autoreleased";
2113 if (PrevV.getCount() > CurrV.getCount())
2114 os <<
"Reference count decremented.";
2116 os <<
"Reference count incremented.";
2118 if (
unsigned Count = CurrV.getCount())
2119 os <<
" The object now has a +" <<
Count <<
" retain count.";
2121 if (PrevV.getKind() == RefVal::Released) {
2122 assert(GCEnabled && CurrV.getCount() > 0);
2123 os <<
" The object is not eligible for garbage collection until "
2124 "the retain count reaches 0 again.";
2129 case RefVal::Released:
2130 if (CurrV.getIvarAccessHistory() ==
2131 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
2132 CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
2133 os <<
"Strong instance variable relinquished. ";
2135 os <<
"Object released.";
2138 case RefVal::ReturnedOwned:
2140 if (CurrV.getAutoreleaseCount())
2143 os <<
"Object returned to caller as an owning reference (single "
2144 "retain count transferred to caller)";
2147 case RefVal::ReturnedNotOwned:
2148 os <<
"Object returned to caller with a +0 retain count";
2157 E=AEffects.end(); I !=
E; ++
I) {
2164 os <<
"In GC mode an 'autorelease' has no effect.";
2167 os <<
"In GC mode the 'retain' message has no effect.";
2170 os <<
"In GC mode the 'release' message has no effect.";
2176 if (os.str().empty())
2186 for (
const Stmt *Child : S->children())
2187 if (
const Expr *Exp = dyn_cast_or_null<Expr>(Child))
2188 if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2189 P->
addRange(Exp->getSourceRange());
2202 struct AllocationInfo {
2209 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2213 static AllocationInfo
2217 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2218 const MemRegion *FirstBinding =
nullptr;
2254 if (NContext == LeakContext || NContext->
isParentOf(LeakContext))
2255 AllocationNodeInCurrentOrParentContext = N;
2259 if (!InitMethodContext)
2261 const Stmt *CE = CEP->getCallExpr();
2262 if (
const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2263 const Stmt *RecExpr = ME->getInstanceReceiver();
2265 SVal RecV = St->getSVal(RecExpr, NContext);
2267 InitMethodContext = CEP->getCalleeContext();
2278 if (InitMethodContext) {
2283 InterestingMethodContext = InitMethodContext;
2288 assert(N &&
"Could not find allocation node");
2290 FirstBinding =
nullptr;
2293 return AllocationInfo(AllocationNodeInCurrentOrParentContext,
2295 InterestingMethodContext);
2298 std::unique_ptr<PathDiagnosticPiece>
2305 std::unique_ptr<PathDiagnosticPiece>
2316 AllocationInfo AllocI =
2319 const MemRegion* FirstBinding = AllocI.R;
2331 llvm::raw_string_ostream os(sbuf);
2333 os <<
"Object leaked: ";
2336 os <<
"object allocated and stored into '"
2337 << FirstBinding->getString() <<
'\'';
2340 os <<
"allocated object";
2346 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2352 os << (isa<ObjCMethodDecl>(D) ?
" is returned from a method "
2353 :
" is returned from a function ");
2355 if (D->hasAttr<CFReturnsNotRetainedAttr>())
2356 os <<
"that is annotated as CF_RETURNS_NOT_RETAINED";
2357 else if (D->hasAttr<NSReturnsNotRetainedAttr>())
2358 os <<
"that is annotated as NS_RETURNS_NOT_RETAINED";
2362 <<
"') does not start with 'copy', 'mutableCopy', 'alloc' or 'new'."
2363 " This violates the naming convention rules"
2364 " given in the Memory Management Guide for Cocoa";
2368 os <<
"whose name ('" << *FD
2369 <<
"') does not contain 'Copy' or 'Create'. This violates the naming"
2370 " convention rules given in the Memory Management Guide for Core"
2375 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2378 <<
"' is potentially leaked when using garbage collection. Callers "
2379 "of this method do not expect a returned object with a +1 retain "
2380 "count since they expect the object to be managed by the garbage "
2384 os <<
" is not referenced later in this execution path and has a retain "
2385 "count of +" << RV->getCount();
2387 return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
2390 CFRefLeakReport::CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
2391 bool GCEnabled,
const SummaryLogTy &Log,
2394 bool IncludeAllocationLine)
2395 : CFRefReport(D, LOpts, GCEnabled, Log, n, sym,
false) {
2409 AllocationInfo AllocI =
2412 AllocNode = AllocI.N;
2413 AllocBinding = AllocI.R;
2414 markInteresting(AllocI.InterestingMethodContext);
2420 const Stmt *AllocStmt =
nullptr;
2423 AllocStmt = Exit->getCalleeContext()->getCallSite();
2426 assert(AllocStmt &&
"Cannot find allocation statement");
2429 PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2430 AllocNode->getLocationContext());
2431 Location = AllocLocation;
2435 UniqueingLocation = AllocLocation;
2436 UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2439 Description.clear();
2440 llvm::raw_string_ostream os(Description);
2441 os <<
"Potential leak ";
2443 os <<
"(when using garbage collection) ";
2444 os <<
"of an object";
2447 os <<
" stored into '" << AllocBinding->getString() <<
'\'';
2448 if (IncludeAllocationLine) {
2454 addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2462 class RetainCountChecker
2463 :
public Checker< check::Bind,
2467 check::PostStmt<BlockExpr>,
2468 check::PostStmt<CastExpr>,
2469 check::PostStmt<ObjCArrayLiteral>,
2470 check::PostStmt<ObjCDictionaryLiteral>,
2471 check::PostStmt<ObjCBoxedExpr>,
2472 check::PostStmt<ObjCIvarRefExpr>,
2474 check::PreStmt<ReturnStmt>,
2475 check::RegionChanges,
2478 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2479 mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2480 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2481 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2482 mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2484 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2487 mutable SymbolTagMap DeadSymbolTags;
2489 mutable std::unique_ptr<RetainSummaryManager> Summaries;
2490 mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2491 mutable SummaryLogTy SummaryLog;
2492 mutable bool ShouldResetSummaryLog;
2496 mutable bool IncludeAllocationLine;
2500 : ShouldResetSummaryLog(
false),
2503 ~RetainCountChecker()
override { DeleteContainerSeconds(DeadSymbolTags); }
2535 if (ShouldResetSummaryLog)
2538 ShouldResetSummaryLog = !SummaryLog.empty();
2541 CFRefBug *getLeakWithinFunctionBug(
const LangOptions &LOpts,
2542 bool GCEnabled)
const {
2544 if (!leakWithinFunctionGC)
2545 leakWithinFunctionGC.reset(
new Leak(
this,
"Leak of object when using "
2546 "garbage collection"));
2547 return leakWithinFunctionGC.get();
2549 if (!leakWithinFunction) {
2551 leakWithinFunction.reset(
new Leak(
this,
2552 "Leak of object when not using "
2553 "garbage collection (GC) in "
2554 "dual GC/non-GC code"));
2556 leakWithinFunction.reset(
new Leak(
this,
"Leak"));
2559 return leakWithinFunction.get();
2563 CFRefBug *getLeakAtReturnBug(
const LangOptions &LOpts,
bool GCEnabled)
const {
2565 if (!leakAtReturnGC)
2566 leakAtReturnGC.reset(
new Leak(
this,
2567 "Leak of returned object when using "
2568 "garbage collection"));
2569 return leakAtReturnGC.get();
2571 if (!leakAtReturn) {
2573 leakAtReturn.reset(
new Leak(
this,
2574 "Leak of returned object when not using "
2575 "garbage collection (GC) in dual "
2578 leakAtReturn.reset(
new Leak(
this,
"Leak of returned object"));
2581 return leakAtReturn.get();
2585 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx,
2586 bool GCEnabled)
const {
2592 SummariesGC.reset(
new RetainSummaryManager(Ctx,
true, ARCEnabled));
2594 assert(SummariesGC->isARCEnabled() == ARCEnabled);
2595 return *SummariesGC;
2598 Summaries.reset(
new RetainSummaryManager(Ctx,
false, ARCEnabled));
2600 assert(Summaries->isARCEnabled() == ARCEnabled);
2610 const char *NL,
const char *Sep)
const override;
2624 void checkSummary(
const RetainSummary &Summ,
const CallEvent &Call,
2627 void processSummaryOfInlined(
const RetainSummary &Summ,
2634 bool Assumption)
const;
2701 void RetainCountChecker::checkPostStmt(
const BlockExpr *BE,
2711 cast<BlockDataRegion>(state->getSVal(BE,
2727 for ( ; I !=
E; ++
I) {
2728 const VarRegion *VR = I.getCapturedRegion();
2732 Regions.push_back(VR);
2736 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2737 Regions.data() + Regions.size()).getState();
2741 void RetainCountChecker::checkPostStmt(
const CastExpr *CE,
2770 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2781 const Expr *Ex)
const {
2784 for (
const Stmt *Child : Ex->children()) {
2789 state = updateSymbol(state, sym, *T,
MayEscape, hasErr, C);
2791 processNonLeakError(state, Child->getSourceRange(), hasErr, sym,
C);
2812 processObjCLiterals(C, AL);
2818 processObjCLiterals(C, DL);
2821 void RetainCountChecker::checkPostStmt(
const ObjCBoxedExpr *Ex,
2827 if (
SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2843 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2844 if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->
getOriginRegion()))
2855 Kind = RetEffect::CF;
2867 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2877 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2885 State =
setRefBinding(State, Sym, PlusZero.withIvarAccess());
2889 void RetainCountChecker::checkPostCall(
const CallEvent &Call,
2891 RetainSummaryManager &Summaries = getSummaryManager(C);
2892 const RetainSummary *Summ = Summaries.getSummary(Call, C.
getState());
2895 processSummaryOfInlined(*Summ, Call, C);
2898 checkSummary(*Summ, Call, C);
2915 if (PT->isObjCQualifiedIdType() || PT->isObjCIdType() ||
2916 PT->isObjCClassType()) {
2932 void RetainCountChecker::processSummaryOfInlined(
const RetainSummary &Summ,
2938 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
2949 if (MsgInvocation) {
2959 if (RE.
getKind() == RetEffect::NoRetHard) {
2971 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.
getAsRegion());
2975 QualType PointeeTy = ArgRegion->getValueType();
2979 SVal PointeeVal = State->getSVal(ArgRegion);
2987 RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
2996 llvm_unreachable(
"only for out parameters");
3002 void RetainCountChecker::checkSummary(
const RetainSummary &Summ,
3012 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3020 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3031 bool ReceiverIsTracked =
false;
3034 if (MsgInvocation) {
3037 ReceiverIsTracked =
true;
3038 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3051 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3058 if (RE.
getKind() == RetEffect::OwnedWhenTrackedReceiver) {
3059 if (ReceiverIsTracked)
3060 RE = getSummaryManager(C).getObjAllocRetEffect();
3062 RE = RetEffect::MakeNoRet();
3067 llvm_unreachable(
"Unhandled RetEffect.");
3069 case RetEffect::NoRet:
3070 case RetEffect::NoRetHard:
3074 case RetEffect::OwnedAllocatedSymbol:
3075 case RetEffect::OwnedSymbol: {
3091 case RetEffect::GCNotOwnedSymbol:
3092 case RetEffect::NotOwnedSymbol: {
3119 if (ShouldResetSummaryLog) {
3121 ShouldResetSummaryLog =
false;
3123 SummaryLog[NewNode] = &Summ;
3134 if (!IgnoreRetainMsg)
3156 V = V ^ RefVal::ErrorUseAfterRelease;
3157 hasErr = V.getKind();
3166 llvm_unreachable(
"DecRefMsg/IncRefMsg/MakeCollectable already converted");
3170 llvm_unreachable(
"Applies to pointer-to-pointer parameters, which should "
3171 "not have ref state.");
3176 V = V ^ RefVal::ErrorDeallocGC;
3177 hasErr = V.getKind();
3181 switch (V.getKind()) {
3183 llvm_unreachable(
"Invalid RefVal state for an explicit dealloc.");
3186 V = V ^ RefVal::Released;
3189 case RefVal::NotOwned:
3190 V = V ^ RefVal::ErrorDeallocNotOwned;
3191 hasErr = V.getKind();
3197 if (V.getKind() == RefVal::Owned) {
3198 V = V ^ RefVal::NotOwned;
3211 V = V.autorelease();
3219 switch (V.getKind()) {
3221 llvm_unreachable(
"Invalid RefVal state for a retain.");
3223 case RefVal::NotOwned:
3226 case RefVal::Released:
3229 V = (V ^ RefVal::Owned) + 1;
3237 switch (V.getKind()) {
3240 llvm_unreachable(
"Invalid RefVal state for a release.");
3243 assert(V.getCount() > 0);
3244 if (V.getCount() == 1) {
3246 V.getIvarAccessHistory() ==
3247 RefVal::IvarAccessHistory::AccessedDirectly)
3248 V = V ^ RefVal::NotOwned;
3250 V = V ^ RefVal::Released;
3258 case RefVal::NotOwned:
3259 if (V.getCount() > 0) {
3263 }
else if (V.getIvarAccessHistory() ==
3264 RefVal::IvarAccessHistory::AccessedDirectly) {
3269 V = V.releaseViaIvar() ^ RefVal::Released;
3271 V = V ^ RefVal::ErrorReleaseNotOwned;
3272 hasErr = V.getKind();
3276 case RefVal::Released:
3279 V = V ^ RefVal::ErrorUseAfterRelease;
3280 hasErr = V.getKind();
3300 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3308 switch (ErrorKind) {
3310 llvm_unreachable(
"Unhandled error.");
3311 case RefVal::ErrorUseAfterRelease:
3312 if (!useAfterRelease)
3313 useAfterRelease.reset(
new UseAfterRelease(
this));
3314 BT = useAfterRelease.get();
3316 case RefVal::ErrorReleaseNotOwned:
3317 if (!releaseNotOwned)
3318 releaseNotOwned.reset(
new BadRelease(
this));
3319 BT = releaseNotOwned.get();
3321 case RefVal::ErrorDeallocGC:
3323 deallocGC.reset(
new DeallocGC(
this));
3324 BT = deallocGC.get();
3326 case RefVal::ErrorDeallocNotOwned:
3327 if (!deallocNotOwned)
3328 deallocNotOwned.reset(
new DeallocNotOwned(
this));
3329 BT = deallocNotOwned.get();
3334 auto report = std::unique_ptr<BugReport>(
3336 SummaryLog, N, Sym));
3337 report->addRange(ErrorRange);
3364 StringRef FName = II->
getName();
3365 FName = FName.substr(FName.find_first_not_of(
'_'));
3368 bool canEval =
false;
3373 canEval = II->
isStr(
"NSMakeCollectable");
3391 SVal RetVal = state->getSVal(CE->
getArg(0), LCtx);
3397 state = state->BindExpr(CE, LCtx, RetVal,
false);
3404 const RefVal *Binding =
nullptr;
3409 state = state->invalidateRegions(ArgRegion, CE, C.
blockCount(), LCtx,
3425 void RetainCountChecker::checkPreStmt(
const ReturnStmt *S,
3454 switch (X.getKind()) {
3455 case RefVal::Owned: {
3456 unsigned cnt = X.getCount();
3458 X.setCount(cnt - 1);
3459 X = X ^ RefVal::ReturnedOwned;
3463 case RefVal::NotOwned: {
3464 unsigned cnt = X.getCount();
3466 X.setCount(cnt - 1);
3467 X = X ^ RefVal::ReturnedOwned;
3470 X = X ^ RefVal::ReturnedNotOwned;
3493 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3505 RetainSummaryManager &Summaries = getSummaryManager(C);
3511 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3512 RE = Summ->getRetEffect();
3513 }
else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3514 if (!isa<CXXMethodDecl>(FD)) {
3515 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3516 RE = Summ->getRetEffect();
3520 checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3523 void RetainCountChecker::checkReturnWithRetEffect(
const ReturnStmt *S,
3535 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3539 if (X.isReturnedOwned() && X.getCount() == 0) {
3540 if (RE.
getKind() != RetEffect::NoRet) {
3541 bool hasError =
false;
3548 X = X ^ RefVal::ErrorGCLeakReturned;
3555 X = X ^ RefVal::ErrorLeakReturned;
3567 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefLeakReport(
3568 *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3569 SummaryLog, N, Sym, C, IncludeAllocationLine)));
3573 }
else if (X.isReturnedNotOwned()) {
3575 if (X.getIvarAccessHistory() ==
3576 RefVal::IvarAccessHistory::AccessedDirectly) {
3580 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3584 state =
setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3587 ReturnNotOwnedTag(
this,
"ReturnNotOwnedForOwned");
3591 if (!returnNotOwnedForOwned)
3592 returnNotOwnedForOwned.reset(
new ReturnedNotOwnedForOwned(
this));
3594 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefReport(
3607 void RetainCountChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
3610 bool escapes =
true;
3621 escapes = !regionLoc->getRegion()->hasStackStorage();
3629 SVal StoredVal = state->getSVal(regionLoc->getRegion());
3630 if (StoredVal != val)
3631 escapes = (state == (state->bindLoc(*regionLoc, val)));
3637 escapes = !isa<VarRegion>(regionLoc->getRegion());
3645 const VarDecl *VD = LVR->getDecl();
3646 if (VD->hasAttr<CleanupAttr>()) {
3659 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3665 bool Assumption)
const {
3672 RefBindingsTy B = state->get<RefBindings>();
3677 bool changed =
false;
3678 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
3686 B = RefBFactory.remove(B, I.getKey());
3691 state = state->set<RefBindings>(B);
3705 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3707 E = ExplicitRegions.end(); I !=
E; ++
I) {
3709 WhitelistedSymbols.insert(SR->getSymbol());
3712 for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3713 E = invalidated->end(); I!=
E; ++
I) {
3715 if (WhitelistedSymbols.count(sym))
3733 unsigned ACnt = V.getAutoreleaseCount();
3740 unsigned Cnt = V.getCount();
3744 if (V.getKind() == RefVal::ReturnedOwned)
3750 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
3751 V = V.releaseViaIvar();
3758 if (V.getKind() == RefVal::ReturnedOwned)
3759 V = V ^ RefVal::ReturnedNotOwned;
3761 V = V ^ RefVal::NotOwned;
3763 V.setCount(V.getCount() - ACnt);
3764 V.setAutoreleaseCount(0);
3775 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3780 V = V ^ RefVal::ErrorOverAutorelease;
3786 llvm::raw_svector_ostream os(sbuf);
3787 os <<
"Object was autoreleased ";
3788 if (V.getAutoreleaseCount() > 1)
3789 os << V.getAutoreleaseCount() <<
" times but the object ";
3792 os <<
"has a +" << V.getCount() <<
" retain count";
3794 if (!overAutorelease)
3795 overAutorelease.reset(
new OverAutorelease(
this));
3799 new CFRefReport(*overAutorelease, LOpts,
false,
3800 SummaryLog, N, Sym, os.str())));
3818 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3820 else if (V.isOwned())
3822 else if (V.isNotOwned() || V.isReturnedOwned())
3823 hasLeak = (V.getCount() > 0);
3830 Leaked.push_back(sid);
3844 I = Leaked.begin(), E = Leaked.end(); I !=
E; ++
I) {
3848 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3849 : getLeakAtReturnBug(LOpts, GCEnabled);
3850 assert(BT &&
"BugType not initialized.");
3853 new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
3854 IncludeAllocationLine)));
3861 void RetainCountChecker::checkEndFunction(
CheckerContext &Ctx)
const {
3863 RefBindingsTy B = state->get<RefBindings>();
3874 state = handleAutoreleaseCounts(state, Pred,
nullptr, Ctx,
3875 I->first, I->second);
3887 B = state->get<RefBindings>();
3891 state = handleSymbolDeath(state, I->first, I->second, Leaked);
3893 processLeaks(state, Leaked, Ctx, Pred);
3897 RetainCountChecker::getDeadSymbolTag(
SymbolRef sym)
const {
3901 llvm::raw_svector_ostream out(buf);
3902 out <<
"Dead Symbol : ";
3909 void RetainCountChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
3914 RefBindingsTy B = state->get<RefBindings>();
3921 if (
const RefVal *T = B.lookup(Sym)){
3925 state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
3931 state = handleSymbolDeath(state, *I, *
getRefBinding(state, Sym), Leaked);
3935 if (Leaked.empty()) {
3940 Pred = processLeaks(state, Leaked, C, Pred);
3948 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
3949 B = state->get<RefBindings>();
3954 B = F.remove(B, *I);
3956 state = state->set<RefBindings>(B);
3960 void RetainCountChecker::printState(raw_ostream &Out,
ProgramStateRef State,
3961 const char *NL,
const char *Sep)
const {
3963 RefBindingsTy B = State->get<RefBindings>();
3971 Out << I->first <<
" : ";
3972 I->second.print(Out);
3991 namespace objc_retain {
3996 #define createCallEffect(D, KIND)\
3997 ASTContext &Ctx = D->getASTContext();\
3998 LangOptions L = Ctx.getLangOpts();\
3999 RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
4000 const RetainSummary *S = M.get ## KIND ## Summary(D);\
4001 CallEffects CE(S->getRetEffect());\
4002 CE.Receiver = S->getReceiverEffect();\
4003 unsigned N = D->param_size();\
4004 for (unsigned i = 0; i < N; ++i) {\
4005 CE.Args.push_back(S->getArg(i));\
4018 #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...
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).
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
virtual const MemRegion * getOriginRegion() const
Find the region from which this symbol originates.
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 ...
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]];.
i32 captured_struct **param SharedsTy A type which contains references the shared variables *param Shareds Context with the list of shared variables from the p *TaskFunction *param Data Additional data for task generation like final * state
static ObjCSummaryKey getTombstoneKey()
static bool isRetain(const FunctionDecl *FD, StringRef FName)
static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr, const ExplodedNode *N, SymbolRef Sym)
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.
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
ArrayRef< ParmVarDecl * >::const_iterator param_const_iterator
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).
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