From: Fariborz Jahanian Date: Tue, 20 Aug 2013 18:54:39 +0000 (+0000) Subject: ObjectiveC migrator: More tweaking of heuristics X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a46c6c3baa0bb24987b44ac7a5543fa60e8b639e;p=clang ObjectiveC migrator: More tweaking of heuristics for an audited cf function and addition of a test case. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@188816 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp index 439b2d4fe4..0147297c0b 100644 --- a/lib/ARCMigrate/ObjCMT.cpp +++ b/lib/ARCMigrate/ObjCMT.cpp @@ -775,16 +775,22 @@ static bool IsVoidStarType(QualType Ty) { return IsVoidStarType(PT->getPointeeType()); } +/// AuditedType - This routine audits the type AT and returns false if it is one of known +/// CF object types or of the "void *" variety. It returns true if we don't care about the type +/// such as a non-pointer or pointers which have no ownership issues (such as "int *"). static bool -AuditedType (QualType AT) { - if (!AT->isPointerType()) +AuditedType (QualType AT, bool &IsPoniter) { + IsPoniter = (AT->isAnyPointerType() || AT->isBlockPointerType()); + if (!IsPoniter) return true; - if (IsVoidStarType(AT)) - return false; - // FIXME. There isn't much we can say about CF pointer type; or is there? - if (ento::coreFoundation::isCFObjectRef(AT)) + if (ento::coreFoundation::isCFObjectRef(AT) || + IsVoidStarType(AT) || + // If an ObjC object is type, assuming that it is not a CF function and + // that it is an un-audited function. + AT->isObjCObjectPointerType()) return false; + // All other pointers are assumed audited as harmless. return true; } @@ -811,10 +817,10 @@ void ObjCMigrateASTConsumer::migrateCFFunctions( const FunctionDecl *FirstFD = CFFunctionIBCandidates[0]; const FunctionDecl *LastFD = CFFunctionIBCandidates[CFFunctionIBCandidates.size()-1]; - const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n"; + const char *PragmaString = "\nCF_IMPLICIT_BRIDGING_ENABLED\n\n"; edit::Commit commit(*Editor); commit.insertBefore(FirstFD->getLocStart(), PragmaString); - PragmaString = "\nCF_IMPLICIT_BRIDGING_DISABLED\n"; + PragmaString = "\n\nCF_IMPLICIT_BRIDGING_DISABLED\n"; SourceLocation EndLoc = LastFD->getLocEnd(); // get location just past end of function location. EndLoc = PP.getLocForEndOfToken(EndLoc); @@ -837,6 +843,7 @@ bool ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( const FunctionDecl *FuncDecl) { if (FuncDecl->hasBody()) return false; + bool HasAtLeastOnePointer = false; CallEffects CE = CallEffects::getEffect(FuncDecl); if (!FuncDecl->getAttr() && !FuncDecl->getAttr()) { @@ -854,10 +861,14 @@ bool ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( edit::Commit commit(*Editor); commit.insertAfterToken(FuncDecl->getLocEnd(), AnnotationString); Editor->commit(commit); + HasAtLeastOnePointer = true; } - else if (!AuditedType(FuncDecl->getResultType())) + else if (!AuditedType(FuncDecl->getResultType(), HasAtLeastOnePointer)) return false; } + else + HasAtLeastOnePointer = true; + // At this point result type is either annotated or audited. // Now, how about argument types. llvm::ArrayRef AEArgs = CE.getArgs(); @@ -865,18 +876,21 @@ bool ObjCMigrateASTConsumer::migrateAddFunctionAnnotation( for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { ArgEffect AE = AEArgs[i]; - if (AE == DecRefMsg /*NSConsumed annotated*/ || - AE == DecRef /*CFConsumed annotated*/) + if (AE == DecRef /*CFConsumed annotated*/ || + AE == IncRef) { + HasAtLeastOnePointer = true; continue; + } - if (AE != DoNothing && AE != MayEscape) - return false; const ParmVarDecl *pd = *pi; QualType AT = pd->getType(); - if (!AuditedType(AT)) + bool IsPointer; + if (!AuditedType(AT, IsPointer)) return false; + else if (IsPointer) + HasAtLeastOnePointer = true; } - return true; + return HasAtLeastOnePointer; } void ObjCMigrateASTConsumer::migrateObjCMethodDeclAnnotation( diff --git a/test/ARCMT/objcmt-arc-cf-annotations.m b/test/ARCMT/objcmt-arc-cf-annotations.m index ea041f1202..91eaecc1c6 100644 --- a/test/ARCMT/objcmt-arc-cf-annotations.m +++ b/test/ARCMT/objcmt-arc-cf-annotations.m @@ -3,6 +3,22 @@ // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result // RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result +#ifndef CF_IMPLICIT_BRIDGING_ENABLED +#if __has_feature(arc_cf_code_audited) +#define CF_IMPLICIT_BRIDGING_ENABLED _Pragma("clang arc_cf_code_audited begin") +#else +#define CF_IMPLICIT_BRIDGING_ENABLED +#endif +#endif + +#ifndef CF_IMPLICIT_BRIDGING_DISABLED +#if __has_feature(arc_cf_code_audited) +#define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end") +#else +#define CF_IMPLICIT_BRIDGING_DISABLED +#endif +#endif + #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) #endif @@ -2020,3 +2036,8 @@ void rdar13783514(xpc_connection_t connection) { xpc_connection_set_context(connection, [[NSMutableArray alloc] init]); xpc_connection_set_finalizer_f(connection, releaseAfterXPC); } // no-warning + +CFAttributedStringRef CFAttributedCreate(long attributes) CF_RETURNS_RETAINED; +CFTypeID CFGetTypeID(void) { + return 0; +} diff --git a/test/ARCMT/objcmt-arc-cf-annotations.m.result b/test/ARCMT/objcmt-arc-cf-annotations.m.result index e821752620..a9b0ac85cf 100644 --- a/test/ARCMT/objcmt-arc-cf-annotations.m.result +++ b/test/ARCMT/objcmt-arc-cf-annotations.m.result @@ -3,6 +3,22 @@ // RUN: c-arcmt-test -mt-migrate-directory %t | arcmt-test -verify-transformed-files %s.result // RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c %s.result +#ifndef CF_IMPLICIT_BRIDGING_ENABLED +#if __has_feature(arc_cf_code_audited) +#define CF_IMPLICIT_BRIDGING_ENABLED _Pragma("clang arc_cf_code_audited begin") +#else +#define CF_IMPLICIT_BRIDGING_ENABLED +#endif +#endif + +#ifndef CF_IMPLICIT_BRIDGING_DISABLED +#if __has_feature(arc_cf_code_audited) +#define CF_IMPLICIT_BRIDGING_DISABLED _Pragma("clang arc_cf_code_audited end") +#else +#define CF_IMPLICIT_BRIDGING_DISABLED +#endif +#endif + #if __has_feature(attribute_ns_returns_retained) #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) #endif @@ -63,7 +79,13 @@ typedef const struct __CFString * CFStringRef; typedef const struct __CFAllocator * CFAllocatorRef; extern const CFAllocatorRef kCFAllocatorDefault; extern CFTypeRef CFRetain(CFTypeRef cf); + +CF_IMPLICIT_BRIDGING_ENABLED + extern void CFRelease(CFTypeRef cf); + +CF_IMPLICIT_BRIDGING_DISABLED + extern CFTypeRef CFMakeCollectable(CFTypeRef cf); typedef struct { } @@ -204,15 +226,27 @@ typedef io_object_t io_iterator_t; typedef io_object_t io_service_t; typedef struct IONotificationPort * IONotificationPortRef; typedef void (*IOServiceMatchingCallback)( void * refcon, io_iterator_t iterator ); + +CF_IMPLICIT_BRIDGING_ENABLED + io_service_t IOServiceGetMatchingService( mach_port_t masterPort, CFDictionaryRef matching ); kern_return_t IOServiceGetMatchingServices( mach_port_t masterPort, CFDictionaryRef matching, io_iterator_t * existing ); -kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated)); // expected-note {{'IOServiceAddNotification' declared here}} +kern_return_t IOServiceAddNotification( mach_port_t masterPort, const io_name_t notificationType, CFDictionaryRef matching, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) __attribute__((deprecated)); + +CF_IMPLICIT_BRIDGING_DISABLED + // expected-note {{'IOServiceAddNotification' declared here}} kern_return_t IOServiceAddMatchingNotification( IONotificationPortRef notifyPort, const io_name_t notificationType, CFDictionaryRef matching, IOServiceMatchingCallback callback, void * refCon, io_iterator_t * notification ); + +CF_IMPLICIT_BRIDGING_ENABLED + CFMutableDictionaryRef IOServiceMatching( const char * name ) CF_RETURNS_RETAINED; CFMutableDictionaryRef IOServiceNameMatching( const char * name ) CF_RETURNS_RETAINED; CFMutableDictionaryRef IOBSDNameMatching( mach_port_t masterPort, uint32_t options, const char * bsdName ) CF_RETURNS_RETAINED; CFMutableDictionaryRef IOOpenFirmwarePathMatching( mach_port_t masterPort, uint32_t options, const char * path ) CF_RETURNS_RETAINED; CFMutableDictionaryRef IORegistryEntryIDMatching( uint64_t entryID ) CF_RETURNS_RETAINED; + +CF_IMPLICIT_BRIDGING_DISABLED + typedef struct __DASession * DASessionRef; extern DASessionRef DASessionCreate( CFAllocatorRef allocator ) CF_RETURNS_RETAINED; typedef struct __DADisk * DADiskRef; @@ -295,13 +329,25 @@ extern CGGradientRef CGGradientCreateWithColorComponents(CGColorSpaceRef extern CGGradientRef CGGradientCreateWithColors(CGColorSpaceRef space, CFArrayRef colors, const CGFloat locations[]) CF_RETURNS_RETAINED; extern CGGradientRef CGGradientRetain(CGGradientRef gradient); + +CF_IMPLICIT_BRIDGING_ENABLED + extern void CGGradientRelease(CGGradientRef gradient); + +CF_IMPLICIT_BRIDGING_DISABLED + typedef struct CGContext *CGContextRef; extern void CGContextDrawLinearGradient(CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options); + +CF_IMPLICIT_BRIDGING_ENABLED + extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void) CF_RETURNS_RETAINED; +CF_IMPLICIT_BRIDGING_DISABLED + + @interface NSMutableArray : NSObject - (void)addObject:(id)object; + (instancetype)array; @@ -395,8 +441,14 @@ CFDateRef f7() { // Generalization of Create rule. MyDateCreate returns a CFXXXTypeRef, and // has the word create. + +CF_IMPLICIT_BRIDGING_ENABLED + CFDateRef MyDateCreate() CF_RETURNS_RETAINED; +CF_IMPLICIT_BRIDGING_DISABLED + + CFDateRef f8() { CFDateRef date = MyDateCreate(); // expected-warning{{leak}} CFRetain(date); @@ -463,8 +515,14 @@ void f11() { // PR 3337: Handle functions declared using typedefs. typedef CFTypeRef CREATEFUN(); + +CF_IMPLICIT_BRIDGING_ENABLED + CFTypeRef MyCreateFun() CF_RETURNS_RETAINED; +CF_IMPLICIT_BRIDGING_DISABLED + + void f12() { CFTypeRef o = MyCreateFun(); // expected-warning {{leak}} } @@ -944,8 +1002,14 @@ void IOServiceNameMatching_wrapper(const char * name) { IOServiceNameMatching(name); // expected-warning{{leak}} } + +CF_IMPLICIT_BRIDGING_ENABLED + CF_RETURNS_RETAINED CFDictionaryRef CreateDict(); +CF_IMPLICIT_BRIDGING_DISABLED + + void IOServiceAddNotification_wrapper(mach_port_t masterPort, const io_name_t notificationType, mach_port_t wakePort, uintptr_t reference, io_iterator_t * notification ) { @@ -1361,8 +1425,14 @@ void testattr3() { } void consume_ns(id NS_CONSUMED x); + +CF_IMPLICIT_BRIDGING_ENABLED + void consume_cf(id CF_CONSUMED x); +CF_IMPLICIT_BRIDGING_DISABLED + + void testattr4() { TestOwnershipAttr *x = [TestOwnershipAttr alloc]; // no-warning consume_ns(x); @@ -1562,7 +1632,13 @@ static void rdar_8724287(CFErrorRef error) // - Make sure the model applies cf_consumed // correctly in argument positions besides the first. + +CF_IMPLICIT_BRIDGING_ENABLED + extern void *CFStringCreate(void) CF_RETURNS_RETAINED; + +CF_IMPLICIT_BRIDGING_DISABLED + extern void rdar_9234108_helper(void *key, void * CF_CONSUMED value); void rdar_9234108() { rdar_9234108_helper(0, CFStringCreate()); @@ -1903,8 +1979,14 @@ id makeCollectableNonLeak() { void consumeAndStopTracking(id NS_CONSUMED obj, void (^callback)(void)); + +CF_IMPLICIT_BRIDGING_ENABLED + void CFConsumeAndStopTracking(CFTypeRef CF_CONSUMED obj, void (^callback)(void)); +CF_IMPLICIT_BRIDGING_DISABLED + + void testConsumeAndStopTracking() { id retained = [@[] retain]; // +1 consumeAndStopTracking(retained, ^{}); // no-warning @@ -1971,9 +2053,15 @@ void test_drain() { // value as tracked, even if the object isn't a known CF type. //===----------------------------------------------------------------------===// + +CF_IMPLICIT_BRIDGING_ENABLED + MyCFType getCustom() __attribute__((cf_returns_not_retained)); MyCFType makeCustom() __attribute__((cf_returns_retained)); +CF_IMPLICIT_BRIDGING_DISABLED + + void testCustomReturnsRetained() { MyCFType obj = makeCustom(); // expected-warning {{leak of an object stored into 'obj'}} } @@ -2020,3 +2108,14 @@ void rdar13783514(xpc_connection_t connection) { xpc_connection_set_context(connection, [[NSMutableArray alloc] init]); xpc_connection_set_finalizer_f(connection, releaseAfterXPC); } // no-warning + + +CF_IMPLICIT_BRIDGING_ENABLED + +CFAttributedStringRef CFAttributedCreate(long attributes) CF_RETURNS_RETAINED; + +CF_IMPLICIT_BRIDGING_DISABLED + +CFTypeID CFGetTypeID(void) { + return 0; +}