From: Fariborz Jahanian Date: Fri, 27 Jul 2012 22:37:07 +0000 (+0000) Subject: objective-c arc: When function calls with known CFCreate naming convention X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=533b34fa7bce6aee7a76f962f02afdf022df6d08;p=clang objective-c arc: When function calls with known CFCreate naming convention are cast to retainable types, only suggest CFBridgingRelease/ CFBridgingRetain and not the __bridge casts. // rdar://11923822 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160900 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index bd7f25f6d1..09f12d7ee2 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -2541,6 +2541,7 @@ namespace { ASTContext &Context; ARCConversionTypeClass SourceClass; ARCConversionTypeClass TargetClass; + bool Diagnose; static bool isCFType(QualType type) { // Someday this can use ns_bridged. For now, it has to do this. @@ -2549,8 +2550,9 @@ namespace { public: ARCCastChecker(ASTContext &Context, ARCConversionTypeClass source, - ARCConversionTypeClass target) - : Context(Context), SourceClass(source), TargetClass(target) {} + ARCConversionTypeClass target, bool diagnose) + : Context(Context), SourceClass(source), TargetClass(target), + Diagnose(diagnose) {} using super::Visit; ACCResult Visit(Expr *e) { @@ -2675,14 +2677,15 @@ namespace { if (builtinID == Builtin::BI__builtin___CFStringMakeConstantString) return ACC_bottom; + // Otherwise, it's +0 unless it follows the create convention. + if (ento::coreFoundation::followsCreateRule(fn)) + return Diagnose ? ACC_plusOne + : ACC_invalid; // ACC_plusOne if we start accepting this + // Otherwise, don't do anything implicit with an unaudited function. if (!fn->hasAttr()) return ACC_invalid; - // Otherwise, it's +0 unless it follows the create convention. - if (ento::coreFoundation::followsCreateRule(fn)) - return ACC_invalid; // ACC_plusOne if we start accepting this - return ACC_plusZero; } @@ -2856,6 +2859,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castRange << castExpr->getSourceRange(); bool br = S.isKnownName("CFBridgingRelease"); + bool fCreateRule = + ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr) + == ACC_plusOne; + if (!fCreateRule) { DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, @@ -2884,7 +2891,10 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << castType << castRange << castExpr->getSourceRange(); - + bool fCreateRule = + ARCCastChecker(S.Context, exprACTC, castACTC, true).Visit(castExpr) + == ACC_plusOne; + if (!fCreateRule) { DiagnosticBuilder DiagB = S.Diag(noteLoc, diag::note_arc_bridge); addFixitForObjCARCConversion(S, DiagB, CCK, afterLParen, @@ -2965,7 +2975,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, CCK != CCK_ImplicitConversion) return ACR_okay; - switch (ARCCastChecker(Context, exprACTC, castACTC).Visit(castExpr)) { + switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) { // For invalid casts, fall through. case ACC_invalid: break; diff --git a/test/SemaObjC/arc-bridged-cast.m b/test/SemaObjC/arc-bridged-cast.m index c8f4d0d166..f115c29255 100644 --- a/test/SemaObjC/arc-bridged-cast.m +++ b/test/SemaObjC/arc-bridged-cast.m @@ -38,30 +38,27 @@ void to_cf(id obj) { CFTypeRef fixits() { id obj1 = (id)CFCreateSomething(); // expected-error{{cast of C pointer type 'CFTypeRef' (aka 'const void *') to Objective-C pointer type 'id' requires a bridged cast}} \ - // expected-note{{use __bridge to convert directly (no change in ownership)}} \ // expected-note{{use CFBridgingRelease call to transfer ownership of a +1 'CFTypeRef' (aka 'const void *') into ARC}} - // CHECK: fix-it:"{{.*}}":{40:14-40:14}:"__bridge " // CHECK: fix-it:"{{.*}}":{40:17-40:17}:"CFBridgingRelease(" // CHECK: fix-it:"{{.*}}":{40:36-40:36}:")" CFTypeRef cf1 = (CFTypeRef)CreateSomething(); // expected-error{{cast of Objective-C pointer type 'id' to C pointer type 'CFTypeRef' (aka 'const void *') requires a bridged cast}} \ // expected-note{{use __bridge to convert directly (no change in ownership)}} \ // expected-note{{use CFBridgingRetain call to make an ARC object available as a +1 'CFTypeRef' (aka 'const void *')}} - // CHECK: fix-it:"{{.*}}":{47:20-47:20}:"__bridge " - // CHECK: fix-it:"{{.*}}":{47:30-47:30}:"CFBridgingRetain(" - // CHECK: fix-it:"{{.*}}":{47:47-47:47}:")" + // CHECK: fix-it:"{{.*}}":{45:30-45:30}:"CFBridgingRetain(" + // CHECK: fix-it:"{{.*}}":{45:47-45:47}:")" return (obj1); // expected-error{{implicit conversion of Objective-C pointer type 'id' to C pointer type 'CFTypeRef' (aka 'const void *') requires a bridged cast}} \ // expected-note{{use __bridge to convert directly (no change in ownership)}} \ // expected-note{{use CFBridgingRetain call to make an ARC object available as a +1 'CFTypeRef' (aka 'const void *')}} - // CHECK: fix-it:"{{.*}}":{54:10-54:10}:"(__bridge CFTypeRef)" - // CHECK: fix-it:"{{.*}}":{54:10-54:10}:"CFBridgingRetain" + // CHECK: fix-it:"{{.*}}":{51:10-51:10}:"(__bridge CFTypeRef)" + // CHECK: fix-it:"{{.*}}":{51:10-51:10}:"CFBridgingRetain" } CFTypeRef fixitsWithSpace(id obj) { return(obj); // expected-error{{implicit conversion of Objective-C pointer type 'id' to C pointer type 'CFTypeRef' (aka 'const void *') requires a bridged cast}} \ // expected-note{{use __bridge to convert directly (no change in ownership)}} \ // expected-note{{use CFBridgingRetain call to make an ARC object available as a +1 'CFTypeRef' (aka 'const void *')}} - // CHECK: fix-it:"{{.*}}":{62:9-62:9}:"(__bridge CFTypeRef)" - // CHECK: fix-it:"{{.*}}":{62:9-62:9}:" CFBridgingRetain" + // CHECK: fix-it:"{{.*}}":{59:9-59:9}:"(__bridge CFTypeRef)" + // CHECK: fix-it:"{{.*}}":{59:9-59:9}:" CFBridgingRetain" } diff --git a/test/SemaObjC/arc-cf.m b/test/SemaObjC/arc-cf.m index 69662ea610..8324df6649 100644 --- a/test/SemaObjC/arc-cf.m +++ b/test/SemaObjC/arc-cf.m @@ -14,7 +14,7 @@ extern CFStringRef CFCreateString0(void); void test0() { id x; x = (id) CFMakeString0(); // expected-error {{requires a bridged cast}} expected-note {{__bridge to convert directly}} expected-note {{CFBridgingRelease call to transfer}} - x = (id) CFCreateString0(); // expected-error {{requires a bridged cast}} expected-note {{__bridge to convert directly}} expected-note {{CFBridgingRelease call to transfer}} + x = (id) CFCreateString0(); // expected-error {{requires a bridged cast}} expected-note {{CFBridgingRelease call to transfer}} } extern CFStringRef CFMakeString1(void) __attribute__((cf_returns_not_retained)); @@ -41,5 +41,5 @@ void test2() { x = (id) CFMakeString2(); x = (id) CFCreateString2(); x = (id) CFMakeString3(); // expected-error {{requires a bridged cast}} expected-note {{__bridge to convert directly}} expected-note {{CFBridgingRelease call to transfer}} - x = (id) CFCreateString3(); // expected-error {{requires a bridged cast}} expected-note {{__bridge to convert directly}} expected-note {{CFBridgingRelease call to transfer}} + x = (id) CFCreateString3(); // expected-error {{requires a bridged cast}} expected-note {{CFBridgingRelease call to transfer}} } diff --git a/test/SemaObjC/arc-unbridged-cast.m b/test/SemaObjC/arc-unbridged-cast.m index 7d5a6b007b..6a39e70771 100644 --- a/test/SemaObjC/arc-unbridged-cast.m +++ b/test/SemaObjC/arc-unbridged-cast.m @@ -44,10 +44,10 @@ void test1(int cond) { x = (id) (cond ? (void*) 0 : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} x = (id) (cond ? (CFStringRef) @"help" : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} + x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} x = (id) [object property]; x = (id) (cond ? [object property] : (void*) 0); diff --git a/test/SemaObjCXX/arc-unbridged-cast.mm b/test/SemaObjCXX/arc-unbridged-cast.mm index 0b3ba07eef..f7d2391487 100644 --- a/test/SemaObjCXX/arc-unbridged-cast.mm +++ b/test/SemaObjCXX/arc-unbridged-cast.mm @@ -44,10 +44,10 @@ void test1(int cond) { x = (id) (cond ? (void*) 0 : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} x = (id) (cond ? (CFStringRef) @"help" : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} - x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use CFBridgingRelease call to}} + x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} + x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use CFBridgingRelease call to}} x = (id) [object property]; x = (id) (cond ? [object property] : (void*) 0);