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);
528 MapTy::iterator
I = M.find(K);
542 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
551 const RetainSummary *Summ = I->second;
559 MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
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;
707 void addMethodSummary(
IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
708 const RetainSummary *Summ,
Keywords *... Kws) {
710 Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
714 void addInstMethSummary(
const char *Cls,
const RetainSummary *Summ,
716 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
720 void addClsMethSummary(
const char *Cls,
const RetainSummary *Summ,
722 addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
727 void addClsMethSummary(
IdentifierInfo *II,
const RetainSummary *Summ,
729 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
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();
938 for (ArgEffects::iterator I = CustomArgEffects.begin(),
939 E = CustomArgEffects.end();
942 if (Translated != DefEffect)
943 ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
957 if (
Name->isStr(
"CGBitmapContextCreateWithData") ||
958 Name->isStr(
"dispatch_data_create"))
959 RE = S->getRetEffect();
963 S = getPersistentSummary(RE, RecEffect, DefEffect);
979 if (MC->getMethodFamily() ==
OMF_init && MC->isReceiverSelfOrSuper()) {
983 const Expr *ME = MC->getOriginExpr();
987 RetainSummaryTemplate ModifiableSummaryTemplate(S, *
this);
988 ModifiableSummaryTemplate->setReceiverEffect(
DoNothing);
995 const RetainSummary *
996 RetainSummaryManager::getSummary(
const CallEvent &Call,
998 const RetainSummary *Summ;
1001 Summ = getFunctionSummary(cast<SimpleFunctionCall>(Call).getDecl());
1010 return getPersistentStopSummary();
1014 Summ = getInstanceMethodSummary(Msg, State);
1016 Summ = getClassMethodSummary(Msg);
1021 updateSummaryForCall(Summ, Call);
1023 assert(Summ &&
"Unknown call type?");
1027 const RetainSummary *
1028 RetainSummaryManager::getFunctionSummary(
const FunctionDecl *FD) {
1031 return getDefaultSummary();
1034 FuncSummariesTy::iterator I = FuncSummaries.find(FD);
1035 if (I != FuncSummaries.end())
1039 const RetainSummary *S =
nullptr;
1040 bool AllowAnnotations =
true;
1045 S = getPersistentStopSummary();
1056 StringRef FName = II->
getName();
1060 FName = FName.substr(FName.find_first_not_of(
'_'));
1067 assert(ScratchArgs.isEmpty());
1069 if (FName ==
"pthread_create" || FName ==
"pthread_setspecific") {
1072 S = getPersistentStopSummary();
1073 }
else if (FName ==
"NSMakeCollectable") {
1076 ? getUnarySummary(FT, cfmakecollectable)
1077 : getPersistentStopSummary();
1080 AllowAnnotations =
false;
1081 }
else if (FName ==
"CFPlugInInstanceCreate") {
1083 }
else if (FName ==
"IOBSDNameMatching" ||
1084 FName ==
"IOServiceMatching" ||
1085 FName ==
"IOServiceNameMatching" ||
1086 FName ==
"IORegistryEntrySearchCFProperty" ||
1087 FName ==
"IORegistryEntryIDMatching" ||
1088 FName ==
"IOOpenFirmwarePathMatching") {
1093 }
else if (FName ==
"IOServiceGetMatchingService" ||
1094 FName ==
"IOServiceGetMatchingServices") {
1098 ScratchArgs = AF.add(ScratchArgs, 1,
DecRef);
1100 }
else if (FName ==
"IOServiceAddNotification" ||
1101 FName ==
"IOServiceAddMatchingNotification") {
1104 ScratchArgs = AF.add(ScratchArgs, 2,
DecRef);
1106 }
else if (FName ==
"CVPixelBufferCreateWithBytes") {
1115 }
else if (FName ==
"CGBitmapContextCreateWithData") {
1123 }
else if (FName ==
"CVPixelBufferCreateWithPlanarBytes") {
1131 }
else if (FName ==
"VTCompressionSessionEncodeFrame") {
1139 }
else if (FName ==
"dispatch_set_context" ||
1140 FName ==
"xpc_connection_set_context") {
1149 }
else if (FName.startswith(
"NSLog")) {
1150 S = getDoNothingSummary();
1151 }
else if (FName.startswith(
"NS") &&
1152 (FName.find(
"Insert") != StringRef::npos)) {
1168 S = getUnarySummary(FT, cfretain);
1170 S = getUnarySummary(FT, cfautorelease);
1173 AllowAnnotations =
false;
1175 S = getUnarySummary(FT, cfmakecollectable);
1176 AllowAnnotations =
false;
1178 S = getCFCreateGetRuleSummary(FD);
1188 S = getUnarySummary(FT, cfretain);
1190 S = getCFCreateGetRuleSummary(FD);
1199 S = getCFCreateGetRuleSummary(FD);
1203 if (FD->
hasAttr<CFAuditedTransferAttr>()) {
1204 S = getCFCreateGetRuleSummary(FD);
1213 if (FName[0] ==
'C' && (FName[1] ==
'F' || FName[1] ==
'G')) {
1215 FName = FName.substr(FName.startswith(
"CGCF") ? 4 : 2);
1218 S = getUnarySummary(FT, cfrelease);
1220 assert (ScratchArgs.isEmpty());
1236 ArgEffect E = (StrInStrNoCase(FName,
"InsertValue") != StringRef::npos||
1237 StrInStrNoCase(FName,
"AddValue") != StringRef::npos ||
1238 StrInStrNoCase(FName,
"SetValue") != StringRef::npos ||
1239 StrInStrNoCase(FName,
"AppendValue") != StringRef::npos||
1240 StrInStrNoCase(FName,
"SetAttribute") != StringRef::npos)
1251 S = getDefaultSummary();
1254 if (AllowAnnotations)
1255 updateSummaryFromAnnotations(S, FD);
1257 FuncSummaries[FD] =
S;
1261 const RetainSummary *
1262 RetainSummaryManager::getCFCreateGetRuleSummary(
const FunctionDecl *FD) {
1264 return getCFSummaryCreateRule(FD);
1266 return getCFSummaryGetRule(FD);
1269 const RetainSummary *
1270 RetainSummaryManager::getUnarySummary(
const FunctionType* FT,
1271 UnaryFuncKind func) {
1277 return getPersistentStopSummary();
1279 assert (ScratchArgs.isEmpty());
1283 case cfretain: Effect =
IncRef;
break;
1284 case cfrelease: Effect =
DecRef;
break;
1289 ScratchArgs = AF.add(ScratchArgs, 0, Effect);
1293 const RetainSummary *
1294 RetainSummaryManager::getCFSummaryCreateRule(
const FunctionDecl *FD) {
1295 assert (ScratchArgs.isEmpty());
1297 return getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
1300 const RetainSummary *
1301 RetainSummaryManager::getCFSummaryGetRule(
const FunctionDecl *FD) {
1302 assert (ScratchArgs.isEmpty());
1303 return getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::CF),
1310 if (Ann->getAnnotation() == rcAnnotation)
1327 RetainSummaryManager::getRetEffectFromAnnotations(
QualType RetTy,
1330 if (D->
hasAttr<NSReturnsRetainedAttr>())
1331 return ObjCAllocRetE;
1333 if (D->
hasAttr<NSReturnsNotRetainedAttr>() ||
1334 D->
hasAttr<NSReturnsAutoreleasedAttr>())
1341 if (D->
hasAttr<CFReturnsRetainedAttr>())
1342 return RetEffect::MakeOwned(RetEffect::CF);
1344 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
1345 return RetEffect::MakeNotOwned(RetEffect::CF);
1351 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1356 assert(Summ &&
"Must have a summary to add annotations to.");
1357 RetainSummaryTemplate Template(Summ, *
this);
1360 unsigned parm_idx = 0;
1362 pe = FD->
param_end(); pi != pe; ++pi, ++parm_idx) {
1364 if (pd->
hasAttr<NSConsumedAttr>())
1365 Template->addArg(AF, parm_idx,
DecRefMsg);
1366 else if (pd->
hasAttr<CFConsumedAttr>())
1367 Template->addArg(AF, parm_idx,
DecRef);
1368 else if (pd->
hasAttr<CFReturnsRetainedAttr>()) {
1373 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1383 Template->setRetEffect(*RetE);
1387 RetainSummaryManager::updateSummaryFromAnnotations(
const RetainSummary *&Summ,
1392 assert(Summ &&
"Must have a valid summary to add annotations to");
1393 RetainSummaryTemplate Template(Summ, *
this);
1396 if (MD->
hasAttr<NSConsumesSelfAttr>())
1400 unsigned parm_idx = 0;
1403 pi != pe; ++pi, ++parm_idx) {
1405 if (pd->
hasAttr<NSConsumedAttr>())
1406 Template->addArg(AF, parm_idx,
DecRefMsg);
1407 else if (pd->
hasAttr<CFConsumedAttr>()) {
1408 Template->addArg(AF, parm_idx,
DecRef);
1409 }
else if (pd->
hasAttr<CFReturnsRetainedAttr>()) {
1414 }
else if (pd->
hasAttr<CFReturnsNotRetainedAttr>()) {
1424 Template->setRetEffect(*RetE);
1427 const RetainSummary *
1428 RetainSummaryManager::getStandardMethodSummary(
const ObjCMethodDecl *MD,
1432 RetEffect ResultEff = RetEffect::MakeNoRet();
1455 ResultEff = RetEffect::MakeOwned(RetEffect::CF);
1458 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1462 ResultEff = RetEffect::MakeNotOwned(RetEffect::CF);
1467 ResultEff = ObjCInitRetE;
1475 ResultEff = ObjCAllocRetE;
1477 ResultEff = RetEffect::MakeOwned(RetEffect::CF);
1505 for (
unsigned i = 0, e = S.
getNumArgs(); i != e; ++i) {
1507 if (Slot.substr(Slot.size() - 8).equals_lower(
"delegate")) {
1508 if (ResultEff == ObjCInitRetE)
1509 ResultEff = RetEffect::MakeNoRetHard();
1516 if (ScratchArgs.isEmpty() && ReceiverEff ==
DoNothing &&
1517 ResultEff.
getKind() == RetEffect::NoRet)
1518 return getDefaultSummary();
1520 return getPersistentSummary(ResultEff, ReceiverEff,
MayEscape);
1523 const RetainSummary *
1524 RetainSummaryManager::getInstanceMethodSummary(
const ObjCMethodCall &Msg,
1538 ReceiverClass = PT->getInterfaceDecl();
1550 if (!Method && ReceiverClass)
1553 return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
1554 ObjCMethodSummaries);
1557 const RetainSummary *
1560 ObjCMethodSummariesTy &CachedSummaries) {
1563 const RetainSummary *Summ = CachedSummaries.find(ID, S);
1566 Summ = getStandardMethodSummary(MD, S, RetTy);
1569 updateSummaryFromAnnotations(Summ, MD);
1572 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
1578 void RetainSummaryManager::InitializeClassMethodSummaries() {
1579 assert(ScratchArgs.isEmpty());
1581 addClassMethSummary(
"NSAssertionHandler",
"currentHandler",
1585 ScratchArgs = AF.add(ScratchArgs, 0,
Autorelease);
1586 addClassMethSummary(
"NSAutoreleasePool",
"addObject",
1587 getPersistentSummary(RetEffect::MakeNoRet(),
1591 void RetainSummaryManager::InitializeMethodSummaries() {
1593 assert (ScratchArgs.isEmpty());
1597 const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE,
DecRefMsg);
1606 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE);
1607 const RetainSummary *CFAllocSumm =
1608 getPersistentSummary(RetEffect::MakeOwned(RetEffect::CF));
1611 RetEffect NoRet = RetEffect::MakeNoRet();
1612 const RetainSummary *Summ = getPersistentSummary(NoRet,
IncRefMsg);
1616 Summ = getPersistentSummary(NoRet,
DecRefMsg);
1620 Summ = getPersistentSummary(NoRet,
Dealloc);
1633 const RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
1637 addClassMethSummary(
"NSWindow",
"alloc", NoTrackYet);
1643 addClassMethSummary(
"NSPanel",
"alloc", NoTrackYet);
1648 addClassMethSummary(
"NSNull",
"null", NoTrackYet);
1652 addClassMethSummary(
"NSAutoreleasePool",
"alloc", NoTrackYet);
1653 addClassMethSummary(
"NSAutoreleasePool",
"allocWithZone", NoTrackYet,
false);
1654 addClassMethSummary(
"NSAutoreleasePool",
"new", NoTrackYet);
1657 addInstMethSummary(
"QCRenderer", AllocSumm,
"createSnapshotImageOfType");
1658 addInstMethSummary(
"QCView", AllocSumm,
"createSnapshotImageOfType");
1663 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect");
1664 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGImage",
"fromRect",
1665 "format",
"colorSpace");
1666 addInstMethSummary(
"CIContext", CFAllocSumm,
"createCGLayerWithSize",
"info");
1673 typedef llvm::DenseMap<const ExplodedNode *, const RetainSummary *>
1680 class CFRefBug :
public BugType {
1682 CFRefBug(
const CheckerBase *checker, StringRef name)
1688 virtual const char *getDescription()
const = 0;
1690 virtual bool isLeak()
const {
return false; }
1693 class UseAfterRelease :
public CFRefBug {
1696 : CFRefBug(checker,
"Use-after-release") {}
1698 const char *getDescription()
const override {
1699 return "Reference-counted object is used after it is released";
1703 class BadRelease :
public CFRefBug {
1705 BadRelease(
const CheckerBase *checker) : CFRefBug(checker,
"Bad release") {}
1707 const char *getDescription()
const override {
1708 return "Incorrect decrement of the reference count of an object that is "
1709 "not owned at this point by the caller";
1713 class DeallocGC :
public CFRefBug {
1716 : CFRefBug(checker,
"-dealloc called while using garbage collection") {}
1718 const char *getDescription()
const override {
1719 return "-dealloc called while using garbage collection";
1723 class DeallocNotOwned :
public CFRefBug {
1726 : CFRefBug(checker,
"-dealloc sent to non-exclusively owned object") {}
1728 const char *getDescription()
const override {
1729 return "-dealloc sent to object that may be referenced elsewhere";
1733 class OverAutorelease :
public CFRefBug {
1736 : CFRefBug(checker,
"Object autoreleased too many times") {}
1738 const char *getDescription()
const override {
1739 return "Object autoreleased too many times";
1743 class ReturnedNotOwnedForOwned :
public CFRefBug {
1745 ReturnedNotOwnedForOwned(
const CheckerBase *checker)
1746 : CFRefBug(checker,
"Method should return an owned object") {}
1748 const char *getDescription()
const override {
1749 return "Object with a +0 retain count returned to caller where a +1 "
1750 "(owning) retain count is expected";
1754 class Leak :
public CFRefBug {
1756 Leak(
const CheckerBase *checker, StringRef name) : CFRefBug(checker, name) {
1758 setSuppressOnSink(
true);
1761 const char *getDescription()
const override {
return ""; }
1763 bool isLeak()
const override {
return true; }
1773 const SummaryLogTy &SummaryLog;
1777 CFRefReportVisitor(
SymbolRef sym,
bool gcEnabled,
const SummaryLogTy &
log)
1778 : Sym(sym), SummaryLog(log), GCEnabled(gcEnabled) {}
1780 void Profile(llvm::FoldingSetNodeID &ID)
const override {
1786 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
1796 class CFRefLeakReportVisitor :
public CFRefReportVisitor {
1798 CFRefLeakReportVisitor(
SymbolRef sym,
bool GCEnabled,
1799 const SummaryLogTy &
log)
1800 : CFRefReportVisitor(sym, GCEnabled, log) {}
1806 std::unique_ptr<BugReporterVisitor> clone()
const override {
1812 return llvm::make_unique<CFRefLeakReportVisitor>(*this);
1817 void addGCModeDescription(
const LangOptions &LOpts,
bool GCEnabled);
1820 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1822 bool registerVisitor =
true)
1824 if (registerVisitor)
1825 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1826 addGCModeDescription(LOpts, GCEnabled);
1829 CFRefReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1832 :
BugReport(D, D.getDescription(), endText, n) {
1833 addVisitor(llvm::make_unique<CFRefReportVisitor>(sym, GCEnabled, Log));
1834 addGCModeDescription(LOpts, GCEnabled);
1837 llvm::iterator_range<ranges_iterator> getRanges()
override {
1838 const CFRefBug& BugTy =
static_cast<CFRefBug&
>(getBugType());
1839 if (!BugTy.isLeak())
1841 return llvm::make_range(ranges_iterator(), ranges_iterator());
1845 class CFRefLeakReport :
public CFRefReport {
1848 CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
bool GCEnabled,
1851 bool IncludeAllocationLine);
1854 assert(Location.isValid());
1860 void CFRefReport::addGCModeDescription(
const LangOptions &LOpts,
1862 const char *GCModeDescription =
nullptr;
1864 switch (LOpts.getGC()) {
1867 GCModeDescription =
"Code is compiled to only use garbage collection";
1872 GCModeDescription =
"Code is compiled to use reference counts";
1877 GCModeDescription =
"Code is compiled to use either garbage collection "
1878 "(GC) or reference counts (non-GC). The bug occurs "
1882 GCModeDescription =
"Code is compiled to use either garbage collection "
1883 "(GC) or reference counts (non-GC). The bug occurs "
1889 assert(GCModeDescription &&
"invalid/unknown GC mode");
1890 addExtraText(GCModeDescription);
1895 return isa<IntegerLiteral>(
E) ||
1896 isa<CharacterLiteral>(E) ||
1897 isa<FloatingLiteral>(
E) ||
1898 isa<ObjCBoolLiteralExpr>(E) ||
1899 isa<CXXBoolLiteralExpr>(
E);
1905 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->
getDecl());
1912 std::shared_ptr<PathDiagnosticPiece>
1926 if (!CurrT)
return nullptr;
1928 const RefVal &CurrV = *CurrT;
1934 llvm::raw_string_ostream os(sbuf);
1941 if (isa<ObjCIvarRefExpr>(S) &&
1946 if (isa<ObjCArrayLiteral>(S)) {
1947 os <<
"NSArray literal is an object with a +0 retain count";
1949 else if (isa<ObjCDictionaryLiteral>(S)) {
1950 os <<
"NSDictionary literal is an object with a +0 retain count";
1952 else if (
const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
1954 os <<
"NSNumber literal is an object with a +0 retain count";
1963 os << *BoxClass <<
" b";
1967 os <<
"oxed expression produces an object with a +0 retain count";
1970 else if (isa<ObjCIvarRefExpr>(S)) {
1971 os <<
"Object loaded from instance variable";
1974 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
1976 SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
1978 os <<
"Call to function '" << *FD <<
'\'';
1980 os <<
"function call";
1983 assert(isa<ObjCMessageExpr>(S));
1988 switch (Call->getMessageKind()) {
2001 if (CurrV.getObjKind() == RetEffect::CF) {
2002 if (Sym->getType().isNull()) {
2003 os <<
" returns a Core Foundation object with a ";
2005 os <<
" returns a Core Foundation object of type "
2006 << Sym->getType().getAsString() <<
" with a ";
2012 if (T.isNull() || !isa<ObjCObjectPointerType>(T)) {
2013 os <<
" returns an Objective-C object with a ";
2016 os <<
" returns an instance of "
2021 if (CurrV.isOwned()) {
2022 os <<
"+1 retain count";
2025 assert(CurrV.getObjKind() == RetEffect::CF);
2027 "Core Foundation objects are not automatically garbage collected.";
2031 assert (CurrV.isNotOwned());
2032 os <<
"+0 retain count";
2038 return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
2046 if (
const RetainSummary *Summ = SummaryLog.lookup(OrigNode)) {
2051 if (
const CallExpr *CE = dyn_cast<CallExpr>(S)) {
2057 AI!=AE; ++AI, ++i) {
2061 if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
2065 AEffects.push_back(Summ->getArg(i));
2069 if (
const Expr *receiver = ME->getInstanceReceiver())
2070 if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
2071 .getAsLocSymbol() == Sym) {
2073 AEffects.push_back(Summ->getReceiverEffect());
2080 RefVal PrevV = *PrevT;
2083 if (!GCEnabled && std::find(AEffects.begin(), AEffects.end(),
Dealloc) !=
2086 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2089 if (CurrV.getKind() == RefVal::Released) {
2090 assert(CurrV.getCombinedCounts() == 0);
2091 os <<
"Object released by directly sending the '-dealloc' message";
2102 CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx);
2107 assert(!PrevV.hasSameState(CurrV) &&
"The state should have changed.");
2109 os <<
"In GC mode a call to '" << *FD
2110 <<
"' decrements an object's retain count and registers the "
2111 "object with the garbage collector. ";
2113 if (CurrV.getKind() == RefVal::Released) {
2114 assert(CurrV.getCount() == 0);
2115 os <<
"Since it now has a 0 retain count the object can be "
2116 "automatically collected by the garbage collector.";
2119 os <<
"An object must have a 0 retain count to be garbage collected. "
2120 "After this call its retain count is +" << CurrV.getCount()
2124 os <<
"When GC is not enabled a call to '" << *FD
2125 <<
"' has no effect on its argument.";
2132 if (!PrevV.hasSameState(CurrV))
2133 switch (CurrV.getKind()) {
2135 case RefVal::NotOwned:
2136 if (PrevV.getCount() == CurrV.getCount()) {
2138 if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
2141 assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
2142 os <<
"Object autoreleased";
2146 if (PrevV.getCount() > CurrV.getCount())
2147 os <<
"Reference count decremented.";
2149 os <<
"Reference count incremented.";
2151 if (
unsigned Count = CurrV.getCount())
2152 os <<
" The object now has a +" << Count <<
" retain count.";
2154 if (PrevV.getKind() == RefVal::Released) {
2155 assert(GCEnabled && CurrV.getCount() > 0);
2156 os <<
" The object is not eligible for garbage collection until "
2157 "the retain count reaches 0 again.";
2162 case RefVal::Released:
2163 if (CurrV.getIvarAccessHistory() ==
2164 RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
2165 CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
2166 os <<
"Strong instance variable relinquished. ";
2168 os <<
"Object released.";
2171 case RefVal::ReturnedOwned:
2173 if (CurrV.getAutoreleaseCount())
2176 os <<
"Object returned to caller as an owning reference (single "
2177 "retain count transferred to caller)";
2180 case RefVal::ReturnedNotOwned:
2181 os <<
"Object returned to caller with a +0 retain count";
2190 E=AEffects.end(); I !=
E; ++
I) {
2197 os <<
"In GC mode an 'autorelease' has no effect.";
2200 os <<
"In GC mode the 'retain' message has no effect.";
2203 os <<
"In GC mode the 'release' message has no effect.";
2209 if (os.str().empty())
2215 auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
2220 if (
const Expr *Exp = dyn_cast_or_null<Expr>(Child))
2221 if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
2222 P->addRange(Exp->getSourceRange());
2226 return std::move(P);
2235 struct AllocationInfo {
2242 N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
2246 static AllocationInfo
2250 const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
2251 const MemRegion *FirstBinding =
nullptr;
2287 if (NContext == LeakContext || NContext->
isParentOf(LeakContext))
2288 AllocationNodeInCurrentOrParentContext = N;
2292 if (!InitMethodContext)
2294 const Stmt *CE = CEP->getCallExpr();
2295 if (
const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
2296 const Stmt *RecExpr = ME->getInstanceReceiver();
2298 SVal RecV = St->getSVal(RecExpr, NContext);
2300 InitMethodContext = CEP->getCalleeContext();
2311 if (InitMethodContext) {
2316 InterestingMethodContext = InitMethodContext;
2321 assert(N &&
"Could not find allocation node");
2323 FirstBinding =
nullptr;
2326 return AllocationInfo(AllocationNodeInCurrentOrParentContext,
2328 InterestingMethodContext);
2331 std::unique_ptr<PathDiagnosticPiece>
2338 std::unique_ptr<PathDiagnosticPiece>
2349 AllocationInfo AllocI =
2352 const MemRegion* FirstBinding = AllocI.R;
2364 llvm::raw_string_ostream os(sbuf);
2366 os <<
"Object leaked: ";
2369 os <<
"object allocated and stored into '"
2370 << FirstBinding->getString() <<
'\'';
2373 os <<
"allocated object";
2379 if (RV->getKind() == RefVal::ErrorLeakReturned) {
2385 os << (isa<ObjCMethodDecl>(D) ?
" is returned from a method "
2386 :
" is returned from a function ");
2388 if (D->
hasAttr<CFReturnsNotRetainedAttr>())
2389 os <<
"that is annotated as CF_RETURNS_NOT_RETAINED";
2390 else if (D->
hasAttr<NSReturnsNotRetainedAttr>())
2391 os <<
"that is annotated as NS_RETURNS_NOT_RETAINED";
2395 os <<
"managed by Automatic Reference Counting";
2398 <<
"') does not start with "
2399 "'copy', 'mutableCopy', 'alloc' or 'new'."
2400 " This violates the naming convention rules"
2401 " given in the Memory Management Guide for Cocoa";
2406 os <<
"whose name ('" << *FD
2407 <<
"') does not contain 'Copy' or 'Create'. This violates the naming"
2408 " convention rules given in the Memory Management Guide for Core"
2413 else if (RV->getKind() == RefVal::ErrorGCLeakReturned) {
2416 <<
"' is potentially leaked when using garbage collection. Callers "
2417 "of this method do not expect a returned object with a +1 retain "
2418 "count since they expect the object to be managed by the garbage "
2422 os <<
" is not referenced later in this execution path and has a retain "
2423 "count of +" << RV->getCount();
2425 return llvm::make_unique<PathDiagnosticEventPiece>(L, os.str());
2428 CFRefLeakReport::CFRefLeakReport(CFRefBug &D,
const LangOptions &LOpts,
2429 bool GCEnabled,
const SummaryLogTy &Log,
2432 bool IncludeAllocationLine)
2433 : CFRefReport(D, LOpts, GCEnabled, Log, n, sym,
false) {
2447 AllocationInfo AllocI =
2450 AllocNode = AllocI.N;
2451 AllocBinding = AllocI.R;
2452 markInteresting(AllocI.InterestingMethodContext);
2458 const Stmt *AllocStmt = PathDiagnosticLocation::getStmt(AllocNode);
2459 assert(AllocStmt &&
"Cannot find allocation statement");
2462 PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
2463 AllocNode->getLocationContext());
2464 Location = AllocLocation;
2468 UniqueingLocation = AllocLocation;
2469 UniqueingDecl = AllocNode->getLocationContext()->getDecl();
2472 Description.clear();
2473 llvm::raw_string_ostream os(Description);
2474 os <<
"Potential leak ";
2476 os <<
"(when using garbage collection) ";
2477 os <<
"of an object";
2480 os <<
" stored into '" << AllocBinding->getString() <<
'\'';
2481 if (IncludeAllocationLine) {
2487 addVisitor(llvm::make_unique<CFRefLeakReportVisitor>(sym, GCEnabled, Log));
2495 class RetainCountChecker
2496 :
public Checker< check::Bind,
2500 check::PostStmt<BlockExpr>,
2501 check::PostStmt<CastExpr>,
2502 check::PostStmt<ObjCArrayLiteral>,
2503 check::PostStmt<ObjCDictionaryLiteral>,
2504 check::PostStmt<ObjCBoxedExpr>,
2505 check::PostStmt<ObjCIvarRefExpr>,
2507 check::PreStmt<ReturnStmt>,
2508 check::RegionChanges,
2511 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
2512 mutable std::unique_ptr<CFRefBug> deallocGC, deallocNotOwned;
2513 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
2514 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
2515 mutable std::unique_ptr<CFRefBug> leakWithinFunctionGC, leakAtReturnGC;
2517 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
2520 mutable SymbolTagMap DeadSymbolTags;
2522 mutable std::unique_ptr<RetainSummaryManager> Summaries;
2523 mutable std::unique_ptr<RetainSummaryManager> SummariesGC;
2524 mutable SummaryLogTy SummaryLog;
2525 mutable bool ShouldResetSummaryLog;
2529 mutable bool IncludeAllocationLine;
2533 : ShouldResetSummaryLog(
false),
2536 ~RetainCountChecker()
override { DeleteContainerSeconds(DeadSymbolTags); }
2568 if (ShouldResetSummaryLog)
2571 ShouldResetSummaryLog = !SummaryLog.empty();
2574 CFRefBug *getLeakWithinFunctionBug(
const LangOptions &LOpts,
2575 bool GCEnabled)
const {
2577 if (!leakWithinFunctionGC)
2578 leakWithinFunctionGC.reset(
new Leak(
this,
"Leak of object when using "
2579 "garbage collection"));
2580 return leakWithinFunctionGC.get();
2582 if (!leakWithinFunction) {
2584 leakWithinFunction.reset(
new Leak(
this,
2585 "Leak of object when not using "
2586 "garbage collection (GC) in "
2587 "dual GC/non-GC code"));
2589 leakWithinFunction.reset(
new Leak(
this,
"Leak"));
2592 return leakWithinFunction.get();
2596 CFRefBug *getLeakAtReturnBug(
const LangOptions &LOpts,
bool GCEnabled)
const {
2598 if (!leakAtReturnGC)
2599 leakAtReturnGC.reset(
new Leak(
this,
2600 "Leak of returned object when using "
2601 "garbage collection"));
2602 return leakAtReturnGC.get();
2604 if (!leakAtReturn) {
2606 leakAtReturn.reset(
new Leak(
this,
2607 "Leak of returned object when not using "
2608 "garbage collection (GC) in dual "
2611 leakAtReturn.reset(
new Leak(
this,
"Leak of returned object"));
2614 return leakAtReturn.get();
2618 RetainSummaryManager &getSummaryManager(
ASTContext &Ctx,
2619 bool GCEnabled)
const {
2625 SummariesGC.reset(
new RetainSummaryManager(Ctx,
true, ARCEnabled));
2627 assert(SummariesGC->isARCEnabled() == ARCEnabled);
2628 return *SummariesGC;
2631 Summaries.reset(
new RetainSummaryManager(Ctx,
false, ARCEnabled));
2633 assert(Summaries->isARCEnabled() == ARCEnabled);
2643 const char *NL,
const char *Sep)
const override;
2657 void checkSummary(
const RetainSummary &Summ,
const CallEvent &Call,
2660 void processSummaryOfInlined(
const RetainSummary &Summ,
2667 bool Assumption)
const;
2731 void RetainCountChecker::checkPostStmt(
const BlockExpr *BE,
2741 cast<BlockDataRegion>(state->getSVal(BE,
2757 for ( ; I !=
E; ++
I) {
2758 const VarRegion *VR = I.getCapturedRegion();
2762 Regions.push_back(VR);
2766 state->scanReachableSymbols<StopTrackingCallback>(Regions.data(),
2767 Regions.data() + Regions.size()).getState();
2771 void RetainCountChecker::checkPostStmt(
const CastExpr *CE,
2800 state = updateSymbol(state, Sym, *T, AE, hasErr, C);
2811 const Expr *Ex)
const {
2819 state = updateSymbol(state, sym, *T,
MayEscape, hasErr, C);
2821 processNonLeakError(state, Child->getSourceRange(), hasErr, sym,
C);
2842 processObjCLiterals(C, AL);
2848 processObjCLiterals(C, DL);
2851 void RetainCountChecker::checkPostStmt(
const ObjCBoxedExpr *Ex,
2857 if (
SymbolRef Sym = State->getSVal(Ex, LCtx).getAsSymbol()) {
2873 SymbolRef Sym = State->getSVal(*IVarLoc).getAsSymbol();
2874 if (!Sym || !dyn_cast_or_null<ObjCIvarRegion>(Sym->
getOriginRegion()))
2885 Kind = RetEffect::CF;
2897 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None ||
2907 RefVal PlusZero = RefVal::makeNotOwned(Kind, Ty);
2915 State =
setRefBinding(State, Sym, PlusZero.withIvarAccess());
2919 void RetainCountChecker::checkPostCall(
const CallEvent &Call,
2921 RetainSummaryManager &Summaries = getSummaryManager(C);
2922 const RetainSummary *Summ = Summaries.getSummary(Call, C.
getState());
2925 processSummaryOfInlined(*Summ, Call, C);
2928 checkSummary(*Summ, Call, C);
2962 void RetainCountChecker::processSummaryOfInlined(
const RetainSummary &Summ,
2968 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
2979 if (MsgInvocation) {
2989 if (RE.
getKind() == RetEffect::NoRetHard) {
3001 auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.
getAsRegion());
3005 QualType PointeeTy = ArgRegion->getValueType();
3009 SVal PointeeVal = State->getSVal(ArgRegion);
3017 RefVal::makeNotOwned(RetEffect::CF, PointeeTy));
3026 llvm_unreachable(
"only for out parameters");
3032 void RetainCountChecker::checkSummary(
const RetainSummary &Summ,
3042 for (
unsigned idx = 0, e = CallOrMsg.
getNumArgs(); idx != e; ++idx) {
3050 state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
3061 bool ReceiverIsTracked =
false;
3064 if (MsgInvocation) {
3067 ReceiverIsTracked =
true;
3068 state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
3081 processNonLeakError(state, ErrorRange, hasErr, ErrorSym, C);
3088 if (RE.
getKind() == RetEffect::OwnedWhenTrackedReceiver) {
3089 if (ReceiverIsTracked)
3090 RE = getSummaryManager(C).getObjAllocRetEffect();
3092 RE = RetEffect::MakeNoRet();
3097 llvm_unreachable(
"Unhandled RetEffect.");
3099 case RetEffect::NoRet:
3100 case RetEffect::NoRetHard:
3104 case RetEffect::OwnedSymbol: {
3120 case RetEffect::GCNotOwnedSymbol:
3121 case RetEffect::NotOwnedSymbol: {
3148 if (ShouldResetSummaryLog) {
3150 ShouldResetSummaryLog =
false;
3152 SummaryLog[NewNode] = &Summ;
3163 if (!IgnoreRetainMsg)
3185 V = V ^ RefVal::ErrorUseAfterRelease;
3186 hasErr = V.getKind();
3195 llvm_unreachable(
"DecRefMsg/IncRefMsg/MakeCollectable already converted");
3199 llvm_unreachable(
"Applies to pointer-to-pointer parameters, which should "
3200 "not have ref state.");
3205 V = V ^ RefVal::ErrorDeallocGC;
3206 hasErr = V.getKind();
3210 switch (V.getKind()) {
3212 llvm_unreachable(
"Invalid RefVal state for an explicit dealloc.");
3215 V = V ^ RefVal::Released;
3218 case RefVal::NotOwned:
3219 V = V ^ RefVal::ErrorDeallocNotOwned;
3220 hasErr = V.getKind();
3226 if (V.getKind() == RefVal::Owned) {
3227 V = V ^ RefVal::NotOwned;
3240 V = V.autorelease();
3248 switch (V.getKind()) {
3250 llvm_unreachable(
"Invalid RefVal state for a retain.");
3252 case RefVal::NotOwned:
3255 case RefVal::Released:
3258 V = (V ^ RefVal::Owned) + 1;
3266 switch (V.getKind()) {
3269 llvm_unreachable(
"Invalid RefVal state for a release.");
3272 assert(V.getCount() > 0);
3273 if (V.getCount() == 1) {
3275 V.getIvarAccessHistory() ==
3276 RefVal::IvarAccessHistory::AccessedDirectly)
3277 V = V ^ RefVal::NotOwned;
3279 V = V ^ RefVal::Released;
3287 case RefVal::NotOwned:
3288 if (V.getCount() > 0) {
3292 }
else if (V.getIvarAccessHistory() ==
3293 RefVal::IvarAccessHistory::AccessedDirectly) {
3298 V = V.releaseViaIvar() ^ RefVal::Released;
3300 V = V ^ RefVal::ErrorReleaseNotOwned;
3301 hasErr = V.getKind();
3305 case RefVal::Released:
3308 V = V ^ RefVal::ErrorUseAfterRelease;
3309 hasErr = V.getKind();
3329 if (RV->getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3337 switch (ErrorKind) {
3339 llvm_unreachable(
"Unhandled error.");
3340 case RefVal::ErrorUseAfterRelease:
3341 if (!useAfterRelease)
3342 useAfterRelease.reset(
new UseAfterRelease(
this));
3343 BT = useAfterRelease.get();
3345 case RefVal::ErrorReleaseNotOwned:
3346 if (!releaseNotOwned)
3347 releaseNotOwned.reset(
new BadRelease(
this));
3348 BT = releaseNotOwned.get();
3350 case RefVal::ErrorDeallocGC:
3352 deallocGC.reset(
new DeallocGC(
this));
3353 BT = deallocGC.get();
3355 case RefVal::ErrorDeallocNotOwned:
3356 if (!deallocNotOwned)
3357 deallocNotOwned.reset(
new DeallocNotOwned(
this));
3358 BT = deallocNotOwned.get();
3363 auto report = std::unique_ptr<BugReport>(
3365 SummaryLog, N, Sym));
3366 report->addRange(ErrorRange);
3393 StringRef FName = II->
getName();
3394 FName = FName.substr(FName.find_first_not_of(
'_'));
3397 bool canEval =
false;
3400 bool hasTrustedImplementationAnnotation =
false;
3405 canEval = II->
isStr(
"NSMakeCollectable");
3419 hasTrustedImplementationAnnotation = canEval;
3429 SVal RetVal = state->getSVal(CE->
getArg(0), LCtx);
3431 (hasTrustedImplementationAnnotation && !ResultTy.
isNull())) {
3438 state = state->BindExpr(CE, LCtx, RetVal,
false);
3445 const RefVal *Binding =
nullptr;
3450 state = state->invalidateRegions(
3452 hasTrustedImplementationAnnotation);
3467 void RetainCountChecker::checkPreStmt(
const ReturnStmt *S,
3496 switch (X.getKind()) {
3497 case RefVal::Owned: {
3498 unsigned cnt = X.getCount();
3500 X.setCount(cnt - 1);
3501 X = X ^ RefVal::ReturnedOwned;
3505 case RefVal::NotOwned: {
3506 unsigned cnt = X.getCount();
3508 X.setCount(cnt - 1);
3509 X = X ^ RefVal::ReturnedOwned;
3512 X = X ^ RefVal::ReturnedNotOwned;
3535 state = handleAutoreleaseCounts(state, Pred, &AutoreleaseTag, C, Sym, X);
3547 RetainSummaryManager &Summaries = getSummaryManager(C);
3553 const RetainSummary *Summ = Summaries.getMethodSummary(MD);
3554 RE = Summ->getRetEffect();
3555 }
else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
3556 if (!isa<CXXMethodDecl>(FD)) {
3557 const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
3558 RE = Summ->getRetEffect();
3562 checkReturnWithRetEffect(S, C, Pred, RE, X, Sym, state);
3565 void RetainCountChecker::checkReturnWithRetEffect(
const ReturnStmt *S,
3577 if (X.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3581 if (X.isReturnedOwned() && X.getCount() == 0) {
3582 if (RE.
getKind() != RetEffect::NoRet) {
3583 bool hasError =
false;
3590 X = X ^ RefVal::ErrorGCLeakReturned;
3597 X = X ^ RefVal::ErrorLeakReturned;
3609 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefLeakReport(
3610 *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
3611 SummaryLog, N, Sym, C, IncludeAllocationLine)));
3615 }
else if (X.isReturnedNotOwned()) {
3617 if (X.getIvarAccessHistory() ==
3618 RefVal::IvarAccessHistory::AccessedDirectly) {
3622 X.releaseViaIvar() ^ RefVal::ReturnedOwned);
3626 state =
setRefBinding(state, Sym, X ^ RefVal::ErrorReturnedNotOwned);
3629 ReturnNotOwnedTag(
this,
"ReturnNotOwnedForOwned");
3633 if (!returnNotOwnedForOwned)
3634 returnNotOwnedForOwned.reset(
new ReturnedNotOwnedForOwned(
this));
3636 C.
emitReport(std::unique_ptr<BugReport>(
new CFRefReport(
3649 void RetainCountChecker::checkBind(
SVal loc,
SVal val,
const Stmt *S,
3652 bool escapes =
true;
3663 escapes = !regionLoc->getRegion()->hasStackStorage();
3671 SVal StoredVal = state->getSVal(regionLoc->getRegion());
3672 if (StoredVal != val)
3679 escapes = !isa<VarRegion>(regionLoc->getRegion());
3687 const VarDecl *VD = LVR->getDecl();
3688 if (VD->
hasAttr<CleanupAttr>()) {
3701 state = state->scanReachableSymbols<StopTrackingCallback>(val).getState();
3707 bool Assumption)
const {
3714 RefBindingsTy B = state->get<RefBindings>();
3719 bool changed =
false;
3720 RefBindingsTy::Factory &RefBFactory = state->get_context<RefBindings>();
3722 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I !=
E; ++
I) {
3728 B = RefBFactory.remove(B, I.getKey());
3733 state = state->set<RefBindings>(B);
3748 llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
3750 E = ExplicitRegions.end(); I !=
E; ++
I) {
3752 WhitelistedSymbols.insert(SR->getSymbol());
3755 for (InvalidatedSymbols::const_iterator I=invalidated->begin(),
3756 E = invalidated->end(); I!=
E; ++
I) {
3758 if (WhitelistedSymbols.count(sym))
3776 unsigned ACnt = V.getAutoreleaseCount();
3783 unsigned Cnt = V.getCount();
3787 if (V.getKind() == RefVal::ReturnedOwned)
3793 V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) {
3794 V = V.releaseViaIvar();
3801 if (V.getKind() == RefVal::ReturnedOwned)
3802 V = V ^ RefVal::ReturnedNotOwned;
3804 V = V ^ RefVal::NotOwned;
3806 V.setCount(V.getCount() - ACnt);
3807 V.setAutoreleaseCount(0);
3818 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3823 V = V ^ RefVal::ErrorOverAutorelease;
3829 llvm::raw_svector_ostream os(sbuf);
3830 os <<
"Object was autoreleased ";
3831 if (V.getAutoreleaseCount() > 1)
3832 os << V.getAutoreleaseCount() <<
" times but the object ";
3835 os <<
"has a +" << V.getCount() <<
" retain count";
3837 if (!overAutorelease)
3838 overAutorelease.reset(
new OverAutorelease(
this));
3842 new CFRefReport(*overAutorelease, LOpts,
false,
3843 SummaryLog, N, Sym, os.str())));
3861 if (V.getIvarAccessHistory() != RefVal::IvarAccessHistory::None)
3863 else if (V.isOwned())
3865 else if (V.isNotOwned() || V.isReturnedOwned())
3866 hasLeak = (V.getCount() > 0);
3873 Leaked.push_back(sid);
3887 I = Leaked.begin(), E = Leaked.end(); I !=
E; ++
I) {
3891 CFRefBug *BT = Pred ? getLeakWithinFunctionBug(LOpts, GCEnabled)
3892 : getLeakAtReturnBug(LOpts, GCEnabled);
3893 assert(BT &&
"BugType not initialized.");
3896 new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
3897 IncludeAllocationLine)));
3904 void RetainCountChecker::checkEndFunction(
CheckerContext &Ctx)
const {
3906 RefBindingsTy B = state->get<RefBindings>();
3916 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I !=
E; ++
I) {
3917 state = handleAutoreleaseCounts(state, Pred,
nullptr, Ctx,
3918 I->first, I->second);
3930 B = state->get<RefBindings>();
3933 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I !=
E; ++
I)
3934 state = handleSymbolDeath(state, I->first, I->second, Leaked);
3936 processLeaks(state, Leaked, Ctx, Pred);
3940 RetainCountChecker::getDeadSymbolTag(
SymbolRef sym)
const {
3944 llvm::raw_svector_ostream out(buf);
3945 out <<
"Dead Symbol : ";
3952 void RetainCountChecker::checkDeadSymbols(
SymbolReaper &SymReaper,
3957 RefBindingsTy B = state->get<RefBindings>();
3964 if (
const RefVal *T = B.lookup(Sym)){
3968 state = handleAutoreleaseCounts(state, Pred, Tag, C, Sym, *T);
3974 state = handleSymbolDeath(state, *I, *
getRefBinding(state, Sym), Leaked);
3978 if (Leaked.empty()) {
3983 Pred = processLeaks(state, Leaked, C, Pred);
3991 RefBindingsTy::Factory &F = state->get_context<RefBindings>();
3992 B = state->get<RefBindings>();
3997 B = F.remove(B, *I);
3999 state = state->set<RefBindings>(B);
4003 void RetainCountChecker::printState(raw_ostream &Out,
ProgramStateRef State,
4004 const char *NL,
const char *Sep)
const {
4006 RefBindingsTy B = State->get<RefBindings>();
4013 for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I !=
E; ++
I) {
4014 Out << I->first <<
" : ";
4015 I->second.print(Out);
4034 namespace objc_retain {
4039 #define createCallEffect(D, KIND)\
4040 ASTContext &Ctx = D->getASTContext();\
4041 LangOptions L = Ctx.getLangOpts();\
4042 RetainSummaryManager M(Ctx, L.GCOnly, L.ObjCAutoRefCount);\
4043 const RetainSummary *S = M.get ## KIND ## Summary(D);\
4044 CallEffects CE(S->getRetEffect());\
4045 CE.Receiver = S->getReceiverEffect();\
4046 unsigned N = D->param_size();\
4047 for (unsigned i = 0; i < N; ++i) {\
4048 CE.Args.push_back(S->getArg(i));\
4061 #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
FunctionDecl * getDefinition()
Get the definition for this declaration.
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.
ASTContext & getASTContext()
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.
Stmt - This represents one statement.
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.
virtual bool inTopFrame() const
Return true if the current LocationContext has no caller context.
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
std::string getAsString() const
bool isCocoaObjectRef(QualType T)
llvm::DenseMap< Stmt *, Stmt * > MapTy
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.
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()
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...
static Selector getKeywordSelector(ASTContext &Ctx, IdentifierInfos *...IIs)
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.
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 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 iterator for iterating over Stmt * arrays that contain only Expr *.
const ParmVarDecl *const * param_const_iterator
Represents a prototype with parameter type info, e.g.
static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation)
Returns true if the declaration 'D' is annotated with 'rcAnnotation'.
The argument is treated as potentially escaping, meaning that even when its reference count hits 0 it...
llvm::ImmutableMap< unsigned, ArgEffect > ArgEffects
ArgEffects summarizes the effects of a function/method call on all of its arguments.
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
const MemRegion * StripCasts(bool StripBaseCasts=true) const
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
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type...
static bool isAutorelease(const FunctionDecl *FD, StringRef FName)
bool isObjCQualifiedIdType() const
True if this is equivalent to 'id.
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 StringRef getIdentifier(const Token &Tok)
static bool isSynthesizedAccessor(const StackFrameContext *SFC)
Returns true if this stack frame is for an Objective-C method that is a property getter or setter who...
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.
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()
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
bool isPropertyAccessor() const
dead_iterator dead_end() const
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 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.
const AdditionalKeywords & Keywords
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.
static bool isTrustedReferenceCountImplementation(const FunctionDecl *FD)
Returns true if the function declaration 'FD' contains 'rc_ownership_trusted_implementation' annotate...
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
QualType getPointeeType() const
Gets the type pointed to by this ObjC pointer.
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).
bool isObjCClassType() const
True if this is equivalent to the 'Class' type, i.e.
virtual void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const
See CheckerManager::runCheckersForPrintState.
ObjKind getObjKind() const
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() 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.
static RetEffect MakeOwned(ObjKind o)
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.
bool isObjCIdType() const
True if this is equivalent to the 'id' type, i.e.
SourceLocation getLocStart() const LLVM_READONLY
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