New ObjC warning: circular containers.
This commit adds new warning to prevent user from creating 'circular containers'. Mutable collections from NSFoundation allows user to add collection to itself, e.g.: NSMutableArray *a = [NSMutableArray new]; [a addObject:a]; The code above leads to really weird behaviour (crashes, 'endless' recursion) and retain cycles (collection retains itself) if ARC enabled. Patch checks the following collections: - NSMutableArray, - NSMutableDictionary, - NSMutableSet, - NSMutableOrderedSet, - NSCountedSet. llvm-svn: 231265
This commit is contained in:
@@ -27,7 +27,10 @@ IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
|
||||
"NSMutableArray",
|
||||
"NSDictionary",
|
||||
"NSMutableDictionary",
|
||||
"NSNumber"
|
||||
"NSNumber",
|
||||
"NSMutableSet",
|
||||
"NSCountedSet",
|
||||
"NSMutableOrderedSet"
|
||||
};
|
||||
|
||||
if (!ClassIds[K])
|
||||
@@ -124,6 +127,25 @@ Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSMutableArr_addObject:
|
||||
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
|
||||
break;
|
||||
case NSMutableArr_insertObjectAtIndex: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("insertObject"),
|
||||
&Ctx.Idents.get("atIndex")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSMutableArr_setObjectAtIndexedSubscript: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("setObject"),
|
||||
&Ctx.Idents.get("atIndexedSubscript")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (NSArraySelectors[MK] = Sel);
|
||||
}
|
||||
@@ -209,6 +231,22 @@ Selector NSAPI::getNSDictionarySelector(
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSMutableDict_setObjectForKeyedSubscript: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("setObject"),
|
||||
&Ctx.Idents.get("forKeyedSubscript")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSMutableDict_setValueForKey: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("setValue"),
|
||||
&Ctx.Idents.get("forKey")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (NSDictionarySelectors[MK] = Sel);
|
||||
}
|
||||
@@ -227,6 +265,63 @@ NSAPI::getNSDictionaryMethodKind(Selector Sel) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
|
||||
if (NSSetSelectors[MK].isNull()) {
|
||||
Selector Sel;
|
||||
switch (MK) {
|
||||
case NSMutableSet_addObject:
|
||||
Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
|
||||
break;
|
||||
case NSOrderedSet_insertObjectAtIndex: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("insertObject"),
|
||||
&Ctx.Idents.get("atIndex")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSOrderedSet_setObjectAtIndex: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("setObject"),
|
||||
&Ctx.Idents.get("atIndex")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSOrderedSet_setObjectAtIndexedSubscript: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("setObject"),
|
||||
&Ctx.Idents.get("atIndexedSubscript")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
case NSOrderedSet_replaceObjectAtIndexWithObject: {
|
||||
IdentifierInfo *KeyIdents[] = {
|
||||
&Ctx.Idents.get("replaceObjectAtIndex"),
|
||||
&Ctx.Idents.get("withObject")
|
||||
};
|
||||
Sel = Ctx.Selectors.getSelector(2, KeyIdents);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (NSSetSelectors[MK] = Sel);
|
||||
}
|
||||
|
||||
return NSSetSelectors[MK];
|
||||
}
|
||||
|
||||
Optional<NSAPI::NSSetMethodKind>
|
||||
NSAPI::getNSSetMethodKind(Selector Sel) {
|
||||
for (unsigned i = 0; i != NumNSSetMethods; ++i) {
|
||||
NSSetMethodKind MK = NSSetMethodKind(i);
|
||||
if (Sel == getNSSetSelector(MK))
|
||||
return MK;
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
|
||||
Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
|
||||
bool Instance) const {
|
||||
static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
|
||||
|
||||
Reference in New Issue
Block a user