forked from OSchip/llvm-project
Teach the static analyzer's interpretation of Cocoa conventions to
obey the objc_method_family attribute when provided. Fixes <rdar://problem/9726279>. llvm-svn: 134493
This commit is contained in:
parent
e443ba736b
commit
5c70b06feb
|
@ -17,15 +17,19 @@
|
|||
#include "clang/AST/Type.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class ObjCMethodDecl;
|
||||
|
||||
namespace ento {
|
||||
namespace cocoa {
|
||||
|
||||
enum NamingConvention { NoConvention, CreateRule, InitRule };
|
||||
|
||||
NamingConvention deriveNamingConvention(Selector S);
|
||||
NamingConvention deriveNamingConvention(Selector S, const ObjCMethodDecl *MD);
|
||||
|
||||
static inline bool followsFundamentalRule(Selector S) {
|
||||
return deriveNamingConvention(S) == CreateRule;
|
||||
static inline bool followsFundamentalRule(Selector S,
|
||||
const ObjCMethodDecl *MD) {
|
||||
return deriveNamingConvention(S, MD) == CreateRule;
|
||||
}
|
||||
|
||||
bool isRefType(QualType RetTy, llvm::StringRef Prefix,
|
||||
|
|
|
@ -36,8 +36,10 @@ using llvm::StringRef;
|
|||
// not release it."
|
||||
//
|
||||
|
||||
cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S) {
|
||||
switch (S.getMethodFamily()) {
|
||||
cocoa::NamingConvention cocoa::deriveNamingConvention(Selector S,
|
||||
const ObjCMethodDecl *MD) {
|
||||
switch (MD && MD->hasAttr<ObjCMethodFamilyAttr>()? MD->getMethodFamily()
|
||||
: S.getMethodFamily()) {
|
||||
case OMF_None:
|
||||
case OMF_autorelease:
|
||||
case OMF_dealloc:
|
||||
|
|
|
@ -1349,7 +1349,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
|
|||
if (cocoa::isCocoaObjectRef(RetTy)) {
|
||||
// EXPERIMENTAL: assume the Cocoa conventions for all objects returned
|
||||
// by instance methods.
|
||||
RetEffect E = cocoa::followsFundamentalRule(S)
|
||||
RetEffect E = cocoa::followsFundamentalRule(S, MD)
|
||||
? ObjCAllocRetE : RetEffect::MakeNotOwned(RetEffect::ObjC);
|
||||
|
||||
return getPersistentSummary(E, ReceiverEff, MayEscape);
|
||||
|
@ -1357,7 +1357,7 @@ RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
|
|||
|
||||
// Look for methods that return an owned core foundation object.
|
||||
if (cocoa::isCFObjectRef(RetTy)) {
|
||||
RetEffect E = cocoa::followsFundamentalRule(S)
|
||||
RetEffect E = cocoa::followsFundamentalRule(S, MD)
|
||||
? RetEffect::MakeOwned(RetEffect::CF, true)
|
||||
: RetEffect::MakeNotOwned(RetEffect::CF);
|
||||
|
||||
|
@ -1428,7 +1428,7 @@ RetainSummaryManager::getInstanceMethodSummary(Selector S,
|
|||
assert(ScratchArgs.isEmpty());
|
||||
|
||||
// "initXXX": pass-through for receiver.
|
||||
if (cocoa::deriveNamingConvention(S) == cocoa::InitRule)
|
||||
if (cocoa::deriveNamingConvention(S, MD) == cocoa::InitRule)
|
||||
Summ = getInitMethodSummary(RetTy);
|
||||
else
|
||||
Summ = getCommonMethodSummary(MD, S, RetTy);
|
||||
|
|
|
@ -1462,3 +1462,28 @@ extern void rdar_9234108_helper(void *key, void * CF_CONSUMED value);
|
|||
void rdar_9234108() {
|
||||
rdar_9234108_helper(0, CFStringCreate());
|
||||
}
|
||||
|
||||
// <rdar://problem/9726279> - Make sure that objc_method_family works
|
||||
// to override naming conventions.
|
||||
struct TwoDoubles {
|
||||
double one;
|
||||
double two;
|
||||
};
|
||||
typedef struct TwoDoubles TwoDoubles;
|
||||
|
||||
@interface NSValue (Mine)
|
||||
- (id)_prefix_initWithTwoDoubles:(TwoDoubles)twoDoubles __attribute__((objc_method_family(init)));
|
||||
@end
|
||||
|
||||
@implementation NSValue (Mine)
|
||||
- (id)_prefix_initWithTwoDoubles:(TwoDoubles)twoDoubles
|
||||
{
|
||||
return [self init];
|
||||
}
|
||||
@end
|
||||
|
||||
void rdar9726279() {
|
||||
TwoDoubles twoDoubles = { 0.0, 0.0 };
|
||||
NSValue *value = [[NSValue alloc] _prefix_initWithTwoDoubles:twoDoubles];
|
||||
[value release];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue