forked from OSchip/llvm-project
ObjectiveC migrator: If we find a method that returns a C pointer
of some sort (but not an object, block pointer or CF pointers), and is not annotated with the objc_returns_inner_pointer attribute, we should suggest NS_RETURNS_INNER_POINTER annotation for these methods. llvm-svn: 189707
This commit is contained in:
parent
9d9510d806
commit
d0fbf6cebd
|
@ -48,9 +48,10 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
|
|||
const ObjCImplementationDecl *ImpDecl);
|
||||
void migrateNSEnumDecl(ASTContext &Ctx, const EnumDecl *EnumDcl,
|
||||
const TypedefDecl *TypedefDcl);
|
||||
void migrateInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl);
|
||||
void migrateMethods(ASTContext &Ctx, ObjCContainerDecl *CDecl);
|
||||
void migrateMethodInstanceType(ASTContext &Ctx, ObjCContainerDecl *CDecl,
|
||||
ObjCMethodDecl *OM);
|
||||
void migrateNsReturnsInnerPointer(ASTContext &Ctx, ObjCMethodDecl *OM);
|
||||
void migrateFactoryMethod(ASTContext &Ctx, ObjCContainerDecl *CDecl,
|
||||
ObjCMethodDecl *OM,
|
||||
ObjCInstanceTypeFamily OIT_Family = OIT_None);
|
||||
|
@ -737,7 +738,31 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx,
|
|||
ReplaceWithInstancetype(*this, OM);
|
||||
}
|
||||
|
||||
void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx,
|
||||
static bool TypeIsInnerPointer(QualType T) {
|
||||
if (!T->isAnyPointerType())
|
||||
return false;
|
||||
if (T->isObjCObjectPointerType() || T->isObjCBuiltinType() ||
|
||||
T->isBlockPointerType() || ento::coreFoundation::isCFObjectRef(T))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx,
|
||||
ObjCMethodDecl *OM) {
|
||||
if (OM->hasAttr<ObjCReturnsInnerPointerAttr>())
|
||||
return;
|
||||
|
||||
QualType RT = OM->getResultType();
|
||||
if (!TypeIsInnerPointer(RT) ||
|
||||
!Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition())
|
||||
return;
|
||||
|
||||
edit::Commit commit(*Editor);
|
||||
commit.insertBefore(OM->getLocEnd(), " NS_RETURNS_INNER_POINTER");
|
||||
Editor->commit(commit);
|
||||
}
|
||||
|
||||
void ObjCMigrateASTConsumer::migrateMethods(ASTContext &Ctx,
|
||||
ObjCContainerDecl *CDecl) {
|
||||
// migrate methods which can have instancetype as their result type.
|
||||
for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(),
|
||||
|
@ -745,6 +770,7 @@ void ObjCMigrateASTConsumer::migrateInstanceType(ASTContext &Ctx,
|
|||
M != MEnd; ++M) {
|
||||
ObjCMethodDecl *Method = (*M);
|
||||
migrateMethodInstanceType(Ctx, CDecl, Method);
|
||||
migrateNsReturnsInnerPointer(Ctx, Method);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1177,7 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
|
|||
|
||||
if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) {
|
||||
// migrate methods which can have instancetype as their result type.
|
||||
migrateInstanceType(Ctx, CDecl);
|
||||
migrateMethods(Ctx, CDecl);
|
||||
// annotate methods with CF annotations.
|
||||
migrateARCSafeAnnotation(Ctx, CDecl);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -objcmt-migrate-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11
|
||||
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
|
||||
|
||||
#ifndef NS_RETURNS_INNER_POINTER // defined in iOS 6 for sure
|
||||
#define NS_RETURNS_INNER_POINTER __attribute__((objc_returns_inner_pointer))
|
||||
#endif
|
||||
|
||||
#define CF_IMPLICIT_BRIDGING_ENABLED _Pragma("clang arc_cf_code_audited begin")
|
||||
|
||||
#define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end")
|
||||
|
||||
#if __has_feature(attribute_ns_returns_retained)
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_not_retained)
|
||||
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumes_self)
|
||||
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumed)
|
||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_consumed)
|
||||
#define CF_CONSUMED __attribute__((cf_consumed))
|
||||
#endif
|
||||
#if __has_attribute(ns_returns_autoreleased)
|
||||
#define NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
|
||||
#endif
|
||||
|
||||
CF_IMPLICIT_BRIDGING_ENABLED
|
||||
|
||||
typedef unsigned long CFTypeID;
|
||||
typedef unsigned long CFOptionFlags;
|
||||
typedef unsigned long CFHashCode;
|
||||
|
||||
typedef signed long CFIndex; /*AnyObj*/
|
||||
typedef const struct __CFArray * CFArrayRef;
|
||||
typedef struct {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
} CFRange;
|
||||
|
||||
typedef void (*CFArrayApplierFunction)(const void *value, void *context);
|
||||
|
||||
typedef enum CFComparisonResult : CFIndex CFComparisonResult; enum CFComparisonResult : CFIndex {
|
||||
kCFCompareLessThan = -1L,
|
||||
kCFCompareEqualTo = 0,
|
||||
kCFCompareGreaterThan = 1
|
||||
};
|
||||
|
||||
|
||||
typedef CFComparisonResult (*CFComparatorFunction)(const void *val1, const void *val2, void *context);
|
||||
|
||||
typedef struct __CFArray * CFMutableArrayRef;
|
||||
|
||||
typedef const struct __CFAttributedString *CFAttributedStringRef;
|
||||
typedef struct __CFAttributedString *CFMutableAttributedStringRef;
|
||||
|
||||
typedef const struct __CFAllocator * CFAllocatorRef;
|
||||
|
||||
typedef const struct __CFString * CFStringRef;
|
||||
typedef struct __CFString * CFMutableStringRef;
|
||||
|
||||
typedef const struct __CFDictionary * CFDictionaryRef;
|
||||
typedef struct __CFDictionary * CFMutableDictionaryRef;
|
||||
|
||||
typedef struct CGImage *CGImageRef;
|
||||
|
||||
CF_IMPLICIT_BRIDGING_DISABLED
|
||||
|
||||
@interface I
|
||||
- (void*) ReturnsInnerPointer;
|
||||
- (int*) AlreadyReturnsInnerPointer NS_RETURNS_INNER_POINTER;
|
||||
@end
|
||||
|
||||
@interface UIImage
|
||||
- (CGImageRef)CGImage;
|
||||
@end
|
||||
|
||||
@interface NSData
|
||||
- (void *)bytes;
|
||||
- (void **) ptr_bytes __attribute__((availability(macosx,unavailable)));
|
||||
@end
|
||||
|
||||
@interface NSMutableData
|
||||
- (void *)mutableBytes __attribute__((deprecated)) __attribute__((unavailable));
|
||||
@end
|
|
@ -0,0 +1,102 @@
|
|||
// RUN: rm -rf %t
|
||||
// RUN: %clang_cc1 -objcmt-migrate-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties -triple x86_64-apple-darwin11
|
||||
// RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result
|
||||
// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc -fobjc-default-synthesize-properties %s.result
|
||||
|
||||
#ifndef NS_RETURNS_INNER_POINTER // defined in iOS 6 for sure
|
||||
#define NS_RETURNS_INNER_POINTER __attribute__((objc_returns_inner_pointer))
|
||||
#endif
|
||||
|
||||
#define CF_IMPLICIT_BRIDGING_ENABLED _Pragma("clang arc_cf_code_audited begin")
|
||||
|
||||
#define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end")
|
||||
|
||||
#if __has_feature(attribute_ns_returns_retained)
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_returns_not_retained)
|
||||
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumes_self)
|
||||
#define NS_CONSUMES_SELF __attribute__((ns_consumes_self))
|
||||
#endif
|
||||
#if __has_feature(attribute_ns_consumed)
|
||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
||||
#endif
|
||||
#if __has_feature(attribute_cf_consumed)
|
||||
#define CF_CONSUMED __attribute__((cf_consumed))
|
||||
#endif
|
||||
#if __has_attribute(ns_returns_autoreleased)
|
||||
#define NS_RETURNS_AUTORELEASED __attribute__((ns_returns_autoreleased))
|
||||
#endif
|
||||
|
||||
CF_IMPLICIT_BRIDGING_ENABLED
|
||||
|
||||
typedef unsigned long CFTypeID;
|
||||
typedef unsigned long CFOptionFlags;
|
||||
typedef unsigned long CFHashCode;
|
||||
|
||||
typedef signed long CFIndex; /*AnyObj*/
|
||||
typedef const struct __CFArray * CFArrayRef;
|
||||
typedef struct {
|
||||
CFIndex location;
|
||||
CFIndex length;
|
||||
} CFRange;
|
||||
|
||||
typedef void (*CFArrayApplierFunction)(const void *value, void *context);
|
||||
|
||||
typedef enum CFComparisonResult : CFIndex CFComparisonResult; enum CFComparisonResult : CFIndex {
|
||||
kCFCompareLessThan = -1L,
|
||||
kCFCompareEqualTo = 0,
|
||||
kCFCompareGreaterThan = 1
|
||||
};
|
||||
|
||||
|
||||
typedef CFComparisonResult (*CFComparatorFunction)(const void *val1, const void *val2, void *context);
|
||||
|
||||
typedef struct __CFArray * CFMutableArrayRef;
|
||||
|
||||
typedef const struct __CFAttributedString *CFAttributedStringRef;
|
||||
typedef struct __CFAttributedString *CFMutableAttributedStringRef;
|
||||
|
||||
typedef const struct __CFAllocator * CFAllocatorRef;
|
||||
|
||||
typedef const struct __CFString * CFStringRef;
|
||||
typedef struct __CFString * CFMutableStringRef;
|
||||
|
||||
typedef const struct __CFDictionary * CFDictionaryRef;
|
||||
typedef struct __CFDictionary * CFMutableDictionaryRef;
|
||||
|
||||
typedef struct CGImage *CGImageRef;
|
||||
|
||||
CF_IMPLICIT_BRIDGING_DISABLED
|
||||
|
||||
@interface I
|
||||
- (void*) ReturnsInnerPointer NS_RETURNS_INNER_POINTER;
|
||||
- (int*) AlreadyReturnsInnerPointer NS_RETURNS_INNER_POINTER;
|
||||
@end
|
||||
|
||||
@interface UIImage
|
||||
|
||||
CF_IMPLICIT_BRIDGING_ENABLED
|
||||
|
||||
- (CGImageRef)CGImage;
|
||||
|
||||
CF_IMPLICIT_BRIDGING_DISABLED
|
||||
|
||||
@end
|
||||
|
||||
@interface NSData
|
||||
- (void *)bytes NS_RETURNS_INNER_POINTER;
|
||||
- (void **) ptr_bytes __attribute__((availability(macosx,unavailable))) NS_RETURNS_INNER_POINTER;
|
||||
@end
|
||||
|
||||
@interface NSMutableData
|
||||
- (void *)mutableBytes __attribute__((deprecated)) __attribute__((unavailable)) NS_RETURNS_INNER_POINTER;
|
||||
@end
|
Loading…
Reference in New Issue