diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 67ad469c1c660a16e8970d663918b2985859c5d0..21204f58b35d3e9df0b9f937352b472c7a2ab2c8 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -6922,7 +6922,8 @@ public: bool CfToNs); bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, - QualType DestType, QualType SrcType); + QualType DestType, QualType SrcType, + Expr *SrcExpr); bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index fc3eeb86306dd152ecd8804ecbb6ed9546f1bbbd..42acb607a733ee48744087d06b329d567413273d 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -10640,7 +10640,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; case IncompatiblePointer: if (getLangOpts().ObjC1 && - CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType)) + CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType, SrcExpr)) return false; MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString); DiagKind = @@ -10722,7 +10722,7 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, break; case Incompatible: if (getLangOpts().ObjC1 && - CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType)) + CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType, SrcExpr)) return true; DiagKind = diag::err_typecheck_convert_incompatible; ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 96f2456f9df923ee3d26dae122254e38817a61cc..c0f65ea84d75bccd3ce54a5913210782e448af9b 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -3427,7 +3427,8 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, bool Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, - QualType DestType, QualType SrcType) { + QualType DestType, QualType SrcType, + Expr *SrcExpr) { ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); @@ -3445,9 +3446,18 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, if (CfToNs) { // Implicit conversion from CF to ObjC object is needed. - if (ClassMethod) + if (ClassMethod) { + std::string ExpressionString = "["; + ExpressionString += RelatedClass->getNameAsString(); + ExpressionString += " "; + ExpressionString += ClassMethod->getSelector().getAsString(); + SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + // Provide a fixit: [RelatedClass ClassMethod SrcExpr] Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << ClassMethod->getSelector() << 0; + << SrcType << DestType << ClassMethod->getSelector() << 0 + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) + << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); + } else Diag(Loc, diag::err_objc_bridged_related_unknown_method) << SrcType << DestType << 0; @@ -3456,9 +3466,18 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, } else { // Implicit conversion from ObjC type to CF object is needed. - if (InstanceMethod) + if (InstanceMethod) { + // Provide a fixit: [ObjectExpr InstanceMethod]; + std::string ExpressionString = " "; + ExpressionString += InstanceMethod->getSelector().getAsString(); + ExpressionString += "]"; + SourceLocation SrcExprEndLoc = PP.getLocForEndOfToken(SrcExpr->getLocEnd()); + Diag(Loc, diag::err_objc_bridged_related_known_method) - << SrcType << DestType << InstanceMethod->getSelector() << 1; + << SrcType << DestType << InstanceMethod->getSelector() << 1 + << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") + << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); + } else Diag(Loc, diag::err_objc_bridged_related_unknown_method) << SrcType << DestType << 1; diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 50ea42714fad42ad06fb7c476b22d783b1ccf564..4a67ae7b9ae8b0ce392079d1a5080a71fa52df82 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -6484,7 +6484,7 @@ bool InitializationSequence::Diagnose(Sema &S, QualType FromType = Args[0]->getType(); if (S.getLangOpts().ObjC1) S.CheckObjCBridgeRelatedConversions(Kind.getLocation(), - DestType, FromType); + DestType, FromType, Args[0]); PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType diff --git a/test/FixIt/fixit-objc-bridge-related-attr.m b/test/FixIt/fixit-objc-bridge-related-attr.m new file mode 100644 index 0000000000000000000000000000000000000000..4a81ecd2ff9b863e2b67115c22c61047980bee18 --- /dev/null +++ b/test/FixIt/fixit-objc-bridge-related-attr.m @@ -0,0 +1,35 @@ +// Objective-C recovery +// RUN: not %clang_cc1 -triple x86_64-apple-darwin10 -fdiagnostics-parseable-fixits -x objective-c %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-arc -fdiagnostics-parseable-fixits -x objective-c %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -triple x86_64-apple-darwin10 -fdiagnostics-parseable-fixits -x objective-c++ %s 2>&1 | FileCheck %s +// rdar://15499111 + +typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGColor))) CGColor *CGColorRef; + +@interface NSColor ++ (NSColor *)colorWithCGColor:(CGColorRef)cgColor; +- (CGColorRef)CGColor; +@end + +@interface NSTextField +- (void)setBackgroundColor:(NSColor *)color; +- (NSColor *)backgroundColor; +@end + +NSColor * Test1(NSTextField *textField, CGColorRef newColor) { + textField.backgroundColor = newColor; + return newColor; +} + +CGColorRef Test2(NSTextField *textField, CGColorRef newColor) { + newColor = textField.backgroundColor; // [textField.backgroundColor CGColor] + return textField.backgroundColor; +} +// CHECK: {20:30-20:30}:"[NSColor colorWithCGColor:" +// CHECK: {20:38-20:38}:"]" +// CHECK: {21:9-21:9}:"[NSColor colorWithCGColor:" +// CHECK: {21:17-21:17}:"]" +// CHECK: {25:13-25:13}:"[" +// CHECK: {25:38-25:38}:" CGColor]" +// CHECK: {26:9-26:9}:"[" +// CHECK: {26:34-26:34}:" CGColor]"