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

llvm-svn: 160900
This commit is contained in:
Fariborz Jahanian 2012-07-27 22:37:07 +00:00
parent 86ca9f9e11
commit 36986c6e0f
5 changed files with 34 additions and 27 deletions

View File

@ -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<CFAuditedTransferAttr>())
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;

View File

@ -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"
}

View File

@ -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}}
}

View File

@ -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);

View File

@ -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);