diff --git a/clang/lib/ARCMigrate/ObjCMT.cpp b/clang/lib/ARCMigrate/ObjCMT.cpp index 7efc81f18b18..dfe123fd3017 100644 --- a/clang/lib/ARCMigrate/ObjCMT.cpp +++ b/clang/lib/ARCMigrate/ObjCMT.cpp @@ -230,6 +230,36 @@ static void append_attr(std::string &PropertyString, const char *attr) { PropertyString += attr; } +static +void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString, + const std::string& TypeString, + const char *name) { + const char *argPtr = TypeString.c_str(); + int paren = 0; + while (*argPtr) { + switch (*argPtr) { + case '(': + PropertyString += *argPtr; + paren++; + break; + case ')': + PropertyString += *argPtr; + paren--; + break; + case '^': + PropertyString += '^'; + if (paren == 1) + PropertyString += name; + break; + default: + PropertyString += *argPtr; + break; + } + argPtr++; + } +} + + static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, const ObjCMethodDecl *Setter, const NSAPI &NS, edit::Commit &commit, @@ -245,7 +275,7 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, // Property with no setter may be suggested as a 'readonly' property. if (!Setter) append_attr(PropertyString, "readonly"); - + // Short circuit properties that contain the name "delegate" or "dataSource", // or have exact name "target" to have unsafe_unretained attribute. if (PropertyName.equals("target") || @@ -267,15 +297,17 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, else append_attr(PropertyString, "retain"); } + else if (ArgType->isBlockPointerType()) + append_attr(PropertyString, "copy"); } else if (propertyLifetime == Qualifiers::OCL_Weak) // TODO. More precise determination of 'weak' attribute requires // looking into setter's implementation for backing weak ivar. append_attr(PropertyString, "weak"); else if (RetainableObject) - append_attr(PropertyString, "retain"); + append_attr(PropertyString, + ArgType->isBlockPointerType() ? "copy" : "retain"); } PropertyString += ')'; - QualType RT = Getter->getResultType(); if (!isa(RT)) { // strip off any ARC lifetime qualifier. @@ -287,26 +319,32 @@ static bool rewriteToObjCProperty(const ObjCMethodDecl *Getter, } } PropertyString += " "; - PropertyString += RT.getAsString(Context.getPrintingPolicy()); - char LastChar = PropertyString[PropertyString.size()-1]; - if (LastChar != '*') - PropertyString += " "; + PrintingPolicy SubPolicy(Context.getPrintingPolicy()); + SubPolicy.SuppressStrongLifetime = true; + std::string TypeString = RT.getAsString(SubPolicy); if (LengthOfPrefix > 0) { // property name must strip off "is" and lower case the first character // after that; e.g. isContinuous will become continuous. StringRef PropertyNameStringRef(PropertyNameString); PropertyNameStringRef = PropertyNameStringRef.drop_front(LengthOfPrefix); PropertyNameString = PropertyNameStringRef; - std::string NewPropertyNameString = PropertyNameString; - bool NoLowering = (isUppercase(NewPropertyNameString[0]) && - NewPropertyNameString.size() > 1 && - isUppercase(NewPropertyNameString[1])); + bool NoLowering = (isUppercase(PropertyNameString[0]) && + PropertyNameString.size() > 1 && + isUppercase(PropertyNameString[1])); if (!NoLowering) - NewPropertyNameString[0] = toLowercase(NewPropertyNameString[0]); - PropertyString += NewPropertyNameString; + PropertyNameString[0] = toLowercase(PropertyNameString[0]); } - else + if (RT->isBlockPointerType() || RT->isFunctionPointerType()) + MigrateBlockOrFunctionPointerTypeVariable(PropertyString, + TypeString, + PropertyNameString.c_str()); + else { + char LastChar = TypeString[TypeString.size()-1]; + PropertyString += TypeString; + if (LastChar != '*') + PropertyString += ' '; PropertyString += PropertyNameString; + } SourceLocation StartGetterSelectorLoc = Getter->getSelectorStartLoc(); Selector GetterSelector = Getter->getSelector(); diff --git a/clang/test/ARCMT/objcmt-property.m b/clang/test/ARCMT/objcmt-property.m index 60716c6a98a0..080e87e1b5c9 100644 --- a/clang/test/ARCMT/objcmt-property.m +++ b/clang/test/ARCMT/objcmt-property.m @@ -1,7 +1,7 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11 +// RUN: %clang_cc1 -fblocks -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -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 %s.result +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION #define WEAK_IMPORT_ATTRIBUTE __attribute__((objc_arc_weak_reference_unavailable)) @@ -215,3 +215,12 @@ DEPRECATED - (BOOL)isDouble; // Not a valid property @end + +// rdar://15082818 +@class NSMutableDictionary; + +@interface NSArray +- (id (^)(id, NSArray *, NSMutableDictionary *)) expressionBlock; +- (id (^)(id, NSArray *, NSMutableDictionary *)) MyBlock; +- (void) setMyBlock : (id (^)(id, NSArray *, NSMutableDictionary *)) bl; +@end diff --git a/clang/test/ARCMT/objcmt-property.m.result b/clang/test/ARCMT/objcmt-property.m.result index 7238b7c88a26..27f7c1c05a0c 100644 --- a/clang/test/ARCMT/objcmt-property.m.result +++ b/clang/test/ARCMT/objcmt-property.m.result @@ -1,7 +1,7 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -triple x86_64-apple-darwin11 +// RUN: %clang_cc1 -fblocks -objcmt-migrate-readwrite-property -objcmt-migrate-readonly-property -mt-migrate-directory %t %s -x objective-c -fobjc-runtime-has-weak -fobjc-arc -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 %s.result +// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin10 -fsyntax-only -x objective-c -fobjc-runtime-has-weak -fobjc-arc %s.result #define WEBKIT_OBJC_METHOD_ANNOTATION(ANNOTATION) ANNOTATION #define WEAK_IMPORT_ATTRIBUTE __attribute__((objc_arc_weak_reference_unavailable)) @@ -215,3 +215,12 @@ DEPRECATED - (BOOL)isDouble; // Not a valid property @end + +// rdar://15082818 +@class NSMutableDictionary; + +@interface NSArray +@property (nonatomic, readonly) id (^expressionBlock)(id, NSArray *, NSMutableDictionary *); +@property (nonatomic, copy) id (^MyBlock)(id, NSArray *, NSMutableDictionary *); + +@end