From 381edf5759d163eb1fb0517891b60379543ec4f0 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 16 Dec 2013 22:54:37 +0000 Subject: [PATCH] ObjectiveC. Further improvements of use of objc_bridge_related attribute; eliminate unnecessary diagnostics which is issued elsewhere, fixit now produces a valid AST tree per convention. This results in some simplification in handling of this attribute as well. // rdar://15499111 llvm-svn: 197436 --- .../clang/Basic/DiagnosticSemaKinds.td | 2 - clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Sema/SemaExpr.cpp | 13 ++++--- clang/lib/Sema/SemaExprObjC.cpp | 38 ++++++++++++------- clang/lib/Sema/SemaInit.cpp | 8 ++-- clang/lib/Sema/SemaOverload.cpp | 4 +- .../arc-objcbridge-related-attribute.m | 18 ++++----- .../SemaObjC/objcbridge-related-attribute.m | 18 ++++----- .../objcbridge-related-attribute.mm | 12 ++---- 9 files changed, 63 insertions(+), 52 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 807389cb0208..d9d22ab5adbb 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2466,8 +2466,6 @@ def err_objc_bridged_related_invalid_class : Error< "could not find Objective-C class %0 to convert %1 to %2">; def err_objc_bridged_related_invalid_class_name : Error< "%0 must be name of an Objective-C class to be able to convert %1 to %2">; - def err_objc_bridged_related_unknown_method : Error< - "%0 cannot be directly converted to %1">; def err_objc_bridged_related_known_method : Error< "%0 must be explicitly converted to %1; use %select{%objcclass2|%objcinstance2}3 " "method for this conversion">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 6eefdf0e76a3..1bd423cdde3f 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -6898,7 +6898,7 @@ public: bool CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, QualType SrcType, - Expr *SrcExpr); + Expr *&SrcExpr); bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d1e3c1f41e2e..e4a6102b0675 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6612,6 +6612,13 @@ Sema::CheckSingleAssignmentConstraints(QualType LHSType, ExprResult &RHS, if (getLangOpts().ObjCAutoRefCount) CheckObjCARCConversion(SourceRange(), Ty, E, CCK_ImplicitConversion, DiagnoseCFAudited); + if (getLangOpts().ObjC1 && + CheckObjCBridgeRelatedConversions(E->getLocStart(), + LHSType, E->getType(), E)) { + RHS = Owned(E); + return Compatible; + } + RHS = ImpCastExprToType(E, Ty, Kind); } return result; @@ -10648,9 +10655,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, MayHaveConvFixit = true; break; case IncompatiblePointer: - if (getLangOpts().ObjC1 && - CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType, SrcExpr)) - return false; MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString); DiagKind = (Action == AA_Passing_CFAudited ? @@ -10730,9 +10734,6 @@ bool Sema::DiagnoseAssignmentResult(AssignConvertType ConvTy, DiagKind = diag::err_arc_weak_unavailable_assign; break; case Incompatible: - if (getLangOpts().ObjC1 && - CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType, SrcExpr)) - return true; DiagKind = diag::err_typecheck_convert_incompatible; ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this); MayHaveConvFixit = true; diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 9211772a01dd..905c080e47dd 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -3431,7 +3431,7 @@ bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc, bool Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, QualType DestType, QualType SrcType, - Expr *SrcExpr) { + Expr *&SrcExpr) { ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType); ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType); bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable); @@ -3460,12 +3460,20 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, << SrcType << DestType << ClassMethod->getSelector() << false << FixItHint::CreateInsertion(SrcExpr->getLocStart(), ExpressionString) << FixItHint::CreateInsertion(SrcExprEndLoc, "]"); + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + + QualType receiverType = + Context.getObjCInterfaceType(RelatedClass); + // Argument. + Expr *args[] = { SrcExpr }; + ExprResult msg = BuildClassMessageImplicit(receiverType, false, + ClassMethod->getLocation(), + ClassMethod->getSelector(), ClassMethod, + MultiExprArg(args, 1)); + SrcExpr = msg.take(); + return true; } - else - Diag(Loc, diag::err_objc_bridged_related_unknown_method) - << SrcType << DestType; - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); } else { // Implicit conversion from ObjC type to CF object is needed. @@ -3492,15 +3500,19 @@ Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc, << FixItHint::CreateInsertion(SrcExpr->getLocStart(), "[") << FixItHint::CreateInsertion(SrcExprEndLoc, ExpressionString); } + Diag(RelatedClass->getLocStart(), diag::note_declared_at); + Diag(TDNDecl->getLocStart(), diag::note_declared_at); + + ExprResult msg = + BuildInstanceMessageImplicit(SrcExpr, SrcType, + InstanceMethod->getLocation(), + InstanceMethod->getSelector(), + InstanceMethod, None); + SrcExpr = msg.take(); + return true; } - else - Diag(Loc, diag::err_objc_bridged_related_unknown_method) - << SrcType << DestType; - Diag(RelatedClass->getLocStart(), diag::note_declared_at); - Diag(TDNDecl->getLocStart(), diag::note_declared_at); } - - return true; + return false; } Sema::ARCConversionResult diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 4a67ae7b9ae8..95456e52cc77 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4462,6 +4462,11 @@ void InitializationSequence::InitializeFrom(Sema &S, Expr *Initializer = 0; if (Args.size() == 1) { Initializer = Args[0]; + if (S.getLangOpts().ObjC1 && + S.CheckObjCBridgeRelatedConversions(Initializer->getLocStart(), + DestType, Initializer->getType(), + Initializer)) + Args[0] = Initializer; if (!isa(Initializer)) SourceType = Initializer->getType(); } @@ -6482,9 +6487,6 @@ bool InitializationSequence::Diagnose(Sema &S, case FK_ConversionFailed: { QualType FromType = Args[0]->getType(); - if (S.getLangOpts().ObjC1) - S.CheckObjCBridgeRelatedConversions(Kind.getLocation(), - DestType, FromType, Args[0]); PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed) << (int)Entity.getKind() << DestType diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 3c5caa5b98f1..13337480b0a3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -1298,7 +1298,9 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, bool AllowObjCWritebackConversion = getLangOpts().ObjCAutoRefCount && (Action == AA_Passing || Action == AA_Sending); - + if (getLangOpts().ObjC1) + CheckObjCBridgeRelatedConversions(From->getLocStart(), + ToType, From->getType(), From); ICS = clang::TryImplicitConversion(*this, From, ToType, /*SuppressUserConversions=*/false, AllowExplicit, diff --git a/clang/test/SemaObjC/arc-objcbridge-related-attribute.m b/clang/test/SemaObjC/arc-objcbridge-related-attribute.m index 58485a7e7b46..59daef1ce64b 100644 --- a/clang/test/SemaObjC/arc-objcbridge-related-attribute.m +++ b/clang/test/SemaObjC/arc-objcbridge-related-attribute.m @@ -2,10 +2,10 @@ // rdar://15499111 typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGColor))) CGColor *CGColorRef; // expected-note 5 {{declared here}} -typedef struct __attribute__((objc_bridge_related(NSColor,,CGColor1))) CGColor1 *CGColorRef1; // expected-note 3 {{declared here}} -typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColorRef2; // expected-note 2 {{declared here}} +typedef struct __attribute__((objc_bridge_related(NSColor,,CGColor1))) CGColor1 *CGColorRef1; +typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColorRef2; -@interface NSColor // expected-note 10 {{declared here}} +@interface NSColor // expected-note 5 {{declared here}} + (NSColor *)colorWithCGColor:(CGColorRef)cgColor; - (CGColorRef)CGColor; - (CGColorRef1)CGColor1; @@ -16,7 +16,7 @@ typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColor - (NSColor *)backgroundColor; @end -void foo(NSColor*); +void foo(NSColor*); // expected-note {{passing argument to parameter here}} NSColor * Test1(NSTextField *textField, CGColorRef newColor) { foo(newColor); // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} @@ -25,9 +25,9 @@ NSColor * Test1(NSTextField *textField, CGColorRef newColor) { } NSColor * Test2(NSTextField *textField, CGColorRef1 newColor) { - foo(newColor); // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *'}} - textField.backgroundColor = newColor; // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *__strong'}} - return newColor; // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *'}} + foo(newColor); // expected-warning {{incompatible pointer types passing 'CGColorRef1' (aka 'struct CGColor1 *') to parameter of type 'NSColor *'}} + textField.backgroundColor = newColor; // expected-warning {{incompatible pointer types assigning to 'NSColor *__strong' from 'CGColorRef1' (aka 'struct CGColor1 *')}} + return newColor; // expected-warning {{incompatible pointer types returning 'CGColorRef1' (aka 'struct CGColor1 *') from a function with result type 'NSColor *'}} } CGColorRef Test3(NSTextField *textField, CGColorRef newColor) { @@ -36,6 +36,6 @@ CGColorRef Test3(NSTextField *textField, CGColorRef newColor) { } CGColorRef2 Test4(NSTextField *textField, CGColorRef2 newColor) { - newColor = textField.backgroundColor; // expected-error {{'NSColor *' cannot be directly converted to 'CGColorRef2' (aka 'struct CGColor2 *')}} - return textField.backgroundColor; // expected-error {{'NSColor *' cannot be directly converted to 'CGColorRef2' (aka 'struct CGColor2 *')}} + newColor = textField.backgroundColor; // expected-warning {{incompatible pointer types assigning}} + return textField.backgroundColor; // expected-warning {{incompatible pointer types returning}} } diff --git a/clang/test/SemaObjC/objcbridge-related-attribute.m b/clang/test/SemaObjC/objcbridge-related-attribute.m index 36a82b21c093..06c2e87c5b1f 100644 --- a/clang/test/SemaObjC/objcbridge-related-attribute.m +++ b/clang/test/SemaObjC/objcbridge-related-attribute.m @@ -2,10 +2,10 @@ // rdar://15499111 typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGColor))) CGColor *CGColorRef; // expected-note 5 {{declared here}} -typedef struct __attribute__((objc_bridge_related(NSColor,,CGColor1))) CGColor1 *CGColorRef1; // expected-note 3 {{declared here}} -typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColorRef2; // expected-note 2 {{declared here}} +typedef struct __attribute__((objc_bridge_related(NSColor,,CGColor1))) CGColor1 *CGColorRef1; +typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColorRef2; -@interface NSColor // expected-note 10 {{declared here}} +@interface NSColor // expected-note 5 {{declared here}} + (NSColor *)colorWithCGColor:(CGColorRef)cgColor; - (CGColorRef)CGColor; - (CGColorRef1)CGColor1; @@ -16,7 +16,7 @@ typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor2 *CGColor - (NSColor *)backgroundColor; @end -void foo(NSColor*); +void foo(NSColor*); // expected-note {{passing argument to parameter here}} NSColor * Test1(NSTextField *textField, CGColorRef newColor) { foo(newColor); // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} @@ -25,9 +25,9 @@ NSColor * Test1(NSTextField *textField, CGColorRef newColor) { } NSColor * Test2(NSTextField *textField, CGColorRef1 newColor) { - foo(newColor); // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *'}} - textField.backgroundColor = newColor; // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *'}} - return newColor; // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') cannot be directly converted to 'NSColor *'}} + foo(newColor); // expected-warning {{incompatible pointer types passing 'CGColorRef1'}} + textField.backgroundColor = newColor; // expected-warning {{incompatible pointer types assigning}} + return newColor; // expected-warning {{incompatible pointer types returning}} } CGColorRef Test3(NSTextField *textField, CGColorRef newColor) { @@ -36,6 +36,6 @@ CGColorRef Test3(NSTextField *textField, CGColorRef newColor) { } CGColorRef2 Test4(NSTextField *textField, CGColorRef2 newColor) { - newColor = textField.backgroundColor; // expected-error {{'NSColor *' cannot be directly converted to 'CGColorRef2' (aka 'struct CGColor2 *')}} - return textField.backgroundColor; // expected-error {{'NSColor *' cannot be directly converted to 'CGColorRef2' (aka 'struct CGColor2 *')}} + newColor = textField.backgroundColor; // expected-warning {{incompatible pointer types assigning}} + return textField.backgroundColor; // expected-warning {{incompatible pointer types returning}} } diff --git a/clang/test/SemaObjCXX/objcbridge-related-attribute.mm b/clang/test/SemaObjCXX/objcbridge-related-attribute.mm index 4270b2b8c077..51fd03eb5368 100644 --- a/clang/test/SemaObjCXX/objcbridge-related-attribute.mm +++ b/clang/test/SemaObjCXX/objcbridge-related-attribute.mm @@ -15,17 +15,13 @@ typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGCo NSColor *Test1(NSColor *nsColor, CGColorRef newColor) { nsColor = newColor; // expected-error {{'CGColorRef' (aka 'CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} - NSColor *ns = newColor; // expected-error {{'CGColorRef' (aka 'CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} \ - // expected-error {{cannot initialize a variable of type 'NSColor *' with an lvalue of type 'CGColorRef' (aka 'CGColor *')}} - return newColor; // expected-error {{'CGColorRef' (aka 'CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} \ - // expected-error {{cannot initialize return object of type 'NSColor *' with an lvalue of type 'CGColorRef' (aka 'CGColor *')}} + NSColor *ns = newColor; // expected-error {{'CGColorRef' (aka 'CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} + return newColor; // expected-error {{'CGColorRef' (aka 'CGColor *') must be explicitly converted to 'NSColor *'; use '+colorWithCGColor:' method for this conversion}} } CGColorRef Test2(NSColor *newColor, CGColorRef cgColor) { cgColor = newColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'CGColor *'); use '-CGColor' method for this conversion}} - CGColorRef cg = newColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'CGColor *'); use '-CGColor' method for this conversion}} \ - // expected-error {{cannot initialize a variable of type 'CGColorRef' (aka 'CGColor *') with an lvalue of type 'NSColor *'}} - return newColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'CGColor *'); use '-CGColor' method for this conversion}}\ - // expected-error {{cannot initialize return object of type 'CGColorRef' (aka 'CGColor *') with an lvalue of type 'NSColor *'}} + CGColorRef cg = newColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'CGColor *'); use '-CGColor' method for this conversion}} + return newColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'CGColor *'); use '-CGColor' method for this conversion}} }