r196629 - ObjectiveC. Continuing implementation of objc_bridge_related

Fariborz Jahanian fjahanian at apple.com
Fri Dec 6 16:34:23 PST 2013


Author: fjahanian
Date: Fri Dec  6 18:34:23 2013
New Revision: 196629

URL: http://llvm.org/viewvc/llvm-project?rev=196629&view=rev
Log:
ObjectiveC. Continuing implementation of objc_bridge_related
attribute in sema and issuing a variety of diagnostics lazily 
for misuse of this attribute (and what to do) when converting 
from CF types to ObjectiveC types (and vice versa).
// rdar://15499111

Added:
    cfe/trunk/test/SemaObjC/arc-objcbridge-related-attribute.m
    cfe/trunk/test/SemaObjC/check-objcbridge-related-attribute-lookup.m
    cfe/trunk/test/SemaObjC/objcbridge-related-attribute.m
    cfe/trunk/test/SemaObjCXX/objcbridge-related-attribute.mm
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/lib/Sema/SemaInit.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=196629&r1=196628&r2=196629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec  6 18:34:23 2013
@@ -2468,6 +2468,23 @@ def warn_objc_invalid_bridge : Warning<
 def warn_objc_invalid_bridge_to_cf : Warning<
   "%0 cannot bridge to %1">, InGroup<ObjCBridge>;
 
+// objc_bridge_related attribute diagnostics.
+def err_objc_bridged_related_invalid_class : Error<
+  "could not find ObjectiveC class %0 to convert %1 to %2">;
+def err_objc_bridged_related_invalid_class_name : Error<
+  "%0 must be name of an ObjectiveC class to be able to convert %1 to %2">;
+def err_objc_bridged_related_class_method : Error<
+  "class method %0 for conversion of CF type %1 to an "
+ "ObjectiveC object of type %2 not found">;
+def err_objc_bridged_related_instance_method : Error<
+  "instance method %0 for conversion of an ObjectiveC type %1 to a CF "
+ "object  of type %2 not found">;
+def err_objc_bridged_related_known_method : Error<
+ "%0 must be explicitly converted to %1, use %2 method for this conversion">;
+def err_objc_bridged_related_unknown_method : Error<
+ "%0 must be explicitly converted to %1, define and then use "
+ "%select{a singular class|an instance}3 method in %2 for this conversion">;
+  
 // Function Parameter Semantic Analysis.
 def err_param_with_void_type : Error<"argument may not have 'void' type">;
 def err_void_only_param : Error<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=196629&r1=196628&r2=196629&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Dec  6 18:34:23 2013
@@ -6908,6 +6908,17 @@ public:
   
   void CheckTollFreeBridgeCast(QualType castType, Expr *castExpr);
   
+  bool checkObjCBridgeRelatedComponents(SourceLocation Loc,
+                                        QualType DestType, QualType SrcType,
+                                        ObjCInterfaceDecl *&RelatedClass,
+                                        ObjCMethodDecl *&ClassMethod,
+                                        ObjCMethodDecl *&InstanceMethod,
+                                        TypedefNameDecl *&TDNDecl,
+                                        bool CfToNs);
+  
+  bool CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+                                         QualType DestType, QualType SrcType);
+  
   bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall);
 
   /// \brief Check whether the given new method is a valid override of the

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=196629&r1=196628&r2=196629&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Dec  6 18:34:23 2013
@@ -10639,6 +10639,9 @@ bool Sema::DiagnoseAssignmentResult(Assi
     MayHaveConvFixit = true;
     break;
   case IncompatiblePointer:
+    if (getLangOpts().ObjC1 &&
+        CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType))
+      return false;
     MakeObjCStringLiteralFixItHint(*this, DstType, SrcExpr, Hint, IsNSString);
       DiagKind =
         (Action == AA_Passing_CFAudited ?
@@ -10718,6 +10721,9 @@ bool Sema::DiagnoseAssignmentResult(Assi
     DiagKind = diag::err_arc_weak_unavailable_assign;
     break;
   case Incompatible:
+    if (getLangOpts().ObjC1 &&
+        CheckObjCBridgeRelatedConversions(Loc, DstType, SrcType))
+      return true;
     DiagKind = diag::err_typecheck_convert_incompatible;
     ConvHints.tryToFixConversion(SrcExpr, SrcType, DstType, *this);
     MayHaveConvFixit = true;

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=196629&r1=196628&r2=196629&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Fri Dec  6 18:34:23 2013
@@ -3341,6 +3341,120 @@ void Sema::CheckTollFreeBridgeCast(QualT
   }
 }
 
+
+bool Sema::checkObjCBridgeRelatedComponents(SourceLocation Loc,
+                                            QualType DestType, QualType SrcType,
+                                            ObjCInterfaceDecl *&RelatedClass,
+                                            ObjCMethodDecl *&ClassMethod,
+                                            ObjCMethodDecl *&InstanceMethod,
+                                            TypedefNameDecl *&TDNDecl,
+                                            bool CfToNs) {
+  QualType T = CfToNs ? SrcType : DestType;
+  while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
+    TDNDecl = TD->getDecl();
+    if (ObjCBridgeRelatedAttr *ObjCBAttr =
+          getObjCBridgeAttr<ObjCBridgeRelatedAttr>(TD)) {
+      IdentifierInfo *RCId = ObjCBAttr->getRelatedClass();
+      IdentifierInfo *CMId = ObjCBAttr->getClassMethod();
+      IdentifierInfo *IMId = ObjCBAttr->getInstanceMethod();
+      if (!RCId)
+        return false;
+      NamedDecl *Target = 0;
+      // Check for an existing type with this name.
+      LookupResult R(*this, DeclarationName(RCId), SourceLocation(),
+                     Sema::LookupOrdinaryName);
+      if (!LookupName(R, TUScope)) {
+        Diag(Loc, diag::err_objc_bridged_related_invalid_class) << RCId
+          << SrcType << DestType;
+        Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+        return false;
+      }
+      Target = R.getFoundDecl();
+      if (Target && isa<ObjCInterfaceDecl>(Target))
+        RelatedClass = cast<ObjCInterfaceDecl>(Target);
+      else {
+        Diag(Loc, diag::err_objc_bridged_related_invalid_class_name) << RCId
+          << SrcType << DestType;
+        Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+        if (Target)
+          Diag(Target->getLocStart(), diag::note_declared_at);
+        return false;
+      }
+      
+      // Check for an existing class method with the given selector name.
+      if (CfToNs && CMId) {
+        Selector Sel = Context.Selectors.getUnarySelector(CMId);
+        ClassMethod = RelatedClass->lookupMethod(Sel, false);
+        if (!ClassMethod) {
+          Diag(Loc, diag::err_objc_bridged_related_class_method)
+            << Sel << SrcType << DestType;
+          Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+          return false;
+        }
+      }
+      
+      // Check for an existing instance method with the given selector name.
+      if (!CfToNs && IMId) {
+        Selector Sel = Context.Selectors.getNullarySelector(IMId);
+        InstanceMethod = RelatedClass->lookupMethod(Sel, true);
+        if (!InstanceMethod) {
+          Diag(Loc, diag::err_objc_bridged_related_instance_method)
+            << Sel << SrcType << DestType;
+          Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+          return false;
+        }
+      }
+      return true;
+    }
+    T = TDNDecl->getUnderlyingType();
+  }
+  return false;
+}
+
+bool
+Sema::CheckObjCBridgeRelatedConversions(SourceLocation Loc,
+                                        QualType DestType, QualType SrcType) {
+  ARCConversionTypeClass rhsExprACTC = classifyTypeForARCConversion(SrcType);
+  ARCConversionTypeClass lhsExprACTC = classifyTypeForARCConversion(DestType);
+  bool CfToNs = (rhsExprACTC == ACTC_coreFoundation && lhsExprACTC == ACTC_retainable);
+  bool NsToCf = (rhsExprACTC == ACTC_retainable && lhsExprACTC == ACTC_coreFoundation);
+  if (!CfToNs && !NsToCf)
+    return false;
+  
+  ObjCInterfaceDecl *RelatedClass;
+  ObjCMethodDecl *ClassMethod = 0;
+  ObjCMethodDecl *InstanceMethod = 0;
+  TypedefNameDecl *TDNDecl = 0;
+  if (!checkObjCBridgeRelatedComponents(Loc, DestType, SrcType, RelatedClass,
+                                        ClassMethod, InstanceMethod, TDNDecl, CfToNs))
+    return false;
+  
+  if (CfToNs) {
+    // Implicit conversion from CF to ObjC object is needed.
+    if (ClassMethod)
+      Diag(Loc, diag::err_objc_bridged_related_known_method)
+        << SrcType << DestType << ClassMethod->getSelector() << 0;
+    else
+      Diag(Loc, diag::err_objc_bridged_related_unknown_method)
+        << SrcType << DestType << RelatedClass->getName() << 0;
+    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.
+    if (InstanceMethod)
+      Diag(Loc, diag::err_objc_bridged_related_known_method)
+      << SrcType << DestType << InstanceMethod->getSelector() << 1;
+    else
+      Diag(Loc, diag::err_objc_bridged_related_unknown_method)
+      << SrcType << DestType << RelatedClass->getName() << 1;
+    Diag(RelatedClass->getLocStart(), diag::note_declared_at);
+    Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+  }
+  
+  return true;
+}
+
 Sema::ARCConversionResult
 Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
                              Expr *&castExpr, CheckedConversionKind CCK,

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=196629&r1=196628&r2=196629&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Dec  6 18:34:23 2013
@@ -6482,6 +6482,9 @@ bool InitializationSequence::Diagnose(Se
 
   case FK_ConversionFailed: {
     QualType FromType = Args[0]->getType();
+    if (S.getLangOpts().ObjC1)
+        S.CheckObjCBridgeRelatedConversions(Kind.getLocation(),
+                                            DestType, FromType);
     PartialDiagnostic PDiag = S.PDiag(diag::err_init_conversion_failed)
       << (int)Entity.getKind()
       << DestType

Added: cfe/trunk/test/SemaObjC/arc-objcbridge-related-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/arc-objcbridge-related-attribute.m?rev=196629&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/arc-objcbridge-related-attribute.m (added)
+++ cfe/trunk/test/SemaObjC/arc-objcbridge-related-attribute.m Fri Dec  6 18:34:23 2013
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -fsyntax-only -x objective-c -verify -fobjc-arc -Wno-objc-root-class %s
+// 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}}
+
+ at interface NSColor // expected-note 10 {{declared here}}
++ (NSColor *)colorWithCGColor:(CGColorRef)cgColor;
+- (CGColorRef)CGColor;
+- (CGColorRef1)CGColor1;
+ at end
+
+ at interface NSTextField 
+- (void)setBackgroundColor:(NSColor *)color;
+- (NSColor *)backgroundColor;
+ at end
+
+void foo(NSColor*);
+
+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}} \
+		 // expected-error {{implicit conversion of C pointer type 'CGColorRef' (aka 'struct CGColor *') to Objective-C pointer type 'NSColor *' requires a bridged cast}} \
+		 // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+                 // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef' (aka 'struct CGColor *') into ARC}}
+  textField.backgroundColor = newColor; // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *__strong', use 'colorWithCGColor:' method for this conversion}} \
+					// expected-error {{implicit conversion of C pointer type 'CGColorRef' (aka 'struct CGColor *') to Objective-C pointer type 'NSColor *' requires a bridged cast}} \
+                                        // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+					// expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef' (aka 'struct CGColor *') into ARC}}
+  return newColor; // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *', use 'colorWithCGColor:' method for this conversion}} \
+					// expected-error {{implicit conversion of C pointer type 'CGColorRef' (aka 'struct CGColor *') to Objective-C pointer type 'NSColor *' requires a bridged cast}} \
+                                        // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+					// expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef' (aka 'struct CGColor *') into ARC}}
+}
+
+NSColor * Test2(NSTextField *textField, CGColorRef1 newColor) {
+  foo(newColor); // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *', define and then use a singular class method in NSColor for this conversion}} \
+                 // expected-error {{implicit conversion of C pointer type 'CGColorRef1' (aka 'struct CGColor1 *') to Objective-C pointer type 'NSColor *' requires a bridged cast}} \
+		 // expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+		 // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef1' (aka 'struct CGColor1 *') into ARC}}
+  textField.backgroundColor = newColor;  // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *__strong', define and then use a singular class method in NSColor for this conversion}} \
+                 // expected-error {{implicit conversion of C pointer type 'CGColorRef1' (aka 'struct CGColor1 *') to Objective-C pointer type 'NSColor *' requires a bridged cast}}  \
+		 // expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+		 // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef1' (aka 'struct CGColor1 *') into ARC}}
+  return newColor;  // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *', define and then use a singular class method in NSColor for this conversion}} \
+                 // expected-error {{implicit conversion of C pointer type 'CGColorRef1' (aka 'struct CGColor1 *') to Objective-C pointer type 'NSColor *' requires a bridged cast}} \
+		 // expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+		 // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CGColorRef1' (aka 'struct CGColor1 *') into ARC}}
+}
+
+CGColorRef Test3(NSTextField *textField, CGColorRef newColor) {
+  newColor = textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'struct CGColor *'), use 'CGColor' method for this conversion}} \
+                                        // expected-error {{implicit conversion of Objective-C pointer type 'NSColor *' to C pointer type 'CGColorRef' (aka 'struct CGColor *') requires a bridged cast}} \
+				        // expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+				        // expected-note {{use __bridge_retained to make an ARC object available as a +1 'CGColorRef' (aka 'struct CGColor *')}}
+  return textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'struct CGColor *'), use 'CGColor' method for this conversion}} \
+                                        // expected-error {{implicit conversion of Objective-C pointer type 'NSColor *' to C pointer type 'CGColorRef' (aka 'struct CGColor *') requires a bridged cast}} \
+					// expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+				        // expected-note {{use __bridge_retained to make an ARC object available as a +1 'CGColorRef' (aka 'struct CGColor *')}}
+}
+
+CGColorRef2 Test4(NSTextField *textField, CGColorRef2 newColor) {
+  newColor = textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef2' (aka 'struct CGColor2 *'), define and then use an instance method in NSColor for this conversion}} \
+                                        // expected-error {{implicit conversion of Objective-C pointer type 'NSColor *' to C pointer type 'CGColorRef2' (aka 'struct CGColor2 *') requires a bridged cast}} \
+					// expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+					// expected-note {{use __bridge_retained to make an ARC object available as a +1 'CGColorRef2' (aka 'struct CGColor2 *')}}
+  return textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef2' (aka 'struct CGColor2 *'), define and then use an instance method in NSColor for this conversion}} \
+                                        // expected-error {{implicit conversion of Objective-C pointer type 'NSColor *' to C pointer type 'CGColorRef2' (aka 'struct CGColor2 *') requires a bridged cast}} \
+					// expected-note {{use __bridge to convert directly (no change in ownership)}} \ 
+					// expected-note {{use __bridge_retained to make an ARC object available as a +1 'CGColorRef2' (aka 'struct CGColor2 *')}}
+}

Added: cfe/trunk/test/SemaObjC/check-objcbridge-related-attribute-lookup.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/check-objcbridge-related-attribute-lookup.m?rev=196629&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/check-objcbridge-related-attribute-lookup.m (added)
+++ cfe/trunk/test/SemaObjC/check-objcbridge-related-attribute-lookup.m Fri Dec  6 18:34:23 2013
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -x objective-c -verify -Wno-objc-root-class %s
+// rdar://15499111
+
+typedef struct __attribute__((objc_bridge_related(NSColor,colorXWithCGColor:,CXGColor))) CGColor *CGColorRef; // expected-note 2 {{declared here}}
+
+typedef struct __attribute__((objc_bridge_related(XNSColor,colorWithCGColor:,CGColor))) CGColor1 *CGColorRef1; // expected-note 2 {{declared here}}
+
+typedef struct __attribute__((objc_bridge_related(PNsColor,colorWithCGColor:,CGColor))) CGColor2 *CGColorRef2; // expected-note 2 {{declared here}}
+
+ at interface NSColor
++ (NSColor *)colorWithCGColor:(CGColorRef)cgColor;
+- (CGColorRef)CGColor;
+ at end
+
+ at interface NSTextField 
+- (void)setBackgroundColor:(NSColor *)color;
+- (NSColor *)backgroundColor;
+ at end
+
+typedef int PNsColor; // expected-note 2 {{declared here}}
+
+NSColor * Test1(NSTextField *textField, CGColorRef newColor) {
+ textField.backgroundColor = newColor; // expected-error {{class method 'colorXWithCGColor:' for conversion of CF type 'CGColorRef' (aka 'struct CGColor *') to an ObjectiveC object of type 'NSColor *' not found}} \
+					// expected-warning {{incompatible pointer types assigning to 'NSColor *' from 'CGColorRef' (aka 'struct CGColor *')}}
+ newColor = textField.backgroundColor; // expected-error {{instance method 'CXGColor' for conversion of an ObjectiveC type 'NSColor *' to a CF object  of type 'CGColorRef' (aka 'struct CGColor *') not found}} \
+					// expected-warning {{incompatible pointer types assigning to 'CGColorRef' (aka 'struct CGColor *') from 'NSColor *'}}
+}
+NSColor * Test2(NSTextField *textField, CGColorRef1 newColor) {
+ textField.backgroundColor = newColor; // expected-error {{could not find ObjectiveC class 'XNSColor' to convert 'CGColorRef1' (aka 'struct CGColor1 *') to 'NSColor *'}} \
+				       // expected-warning {{incompatible pointer types assigning to 'NSColor *' from 'CGColorRef1' (aka 'struct CGColor1 *')}}
+ newColor = textField.backgroundColor ; // expected-error {{could not find ObjectiveC class 'XNSColor' to convert 'NSColor *' to 'CGColorRef1' (aka 'struct CGColor1 *')}} \
+					// expected-warning {{incompatible pointer types assigning to 'CGColorRef1' (aka 'struct CGColor1 *') from 'NSColor *'}}
+}
+
+NSColor * Test3(NSTextField *textField, CGColorRef2 newColor) {
+ textField.backgroundColor = newColor; // expected-error {{'PNsColor' must be name of an ObjectiveC class to be able to convert 'CGColorRef2' (aka 'struct CGColor2 *') to 'NSColor *'}} \
+					// expected-warning {{incompatible pointer types assigning to 'NSColor *' from 'CGColorRef2' (aka 'struct CGColor2 *')}}
+ newColor = textField.backgroundColor; // expected-error {{'PNsColor' must be name of an ObjectiveC class to be able to convert 'NSColor *' to 'CGColorRef2' (aka 'struct CGColor2 *')}} \
+					// expected-warning {{incompatible pointer types assigning to 'CGColorRef2' (aka 'struct CGColor2 *') from 'NSColor *'}}
+}
+

Added: cfe/trunk/test/SemaObjC/objcbridge-related-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objcbridge-related-attribute.m?rev=196629&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/objcbridge-related-attribute.m (added)
+++ cfe/trunk/test/SemaObjC/objcbridge-related-attribute.m Fri Dec  6 18:34:23 2013
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -fsyntax-only -x objective-c -verify -Wno-objc-root-class %s
+// 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}}
+
+ at interface NSColor // expected-note 10 {{declared here}}
++ (NSColor *)colorWithCGColor:(CGColorRef)cgColor;
+- (CGColorRef)CGColor;
+- (CGColorRef1)CGColor1;
+ at end
+
+ at interface NSTextField 
+- (void)setBackgroundColor:(NSColor *)color;
+- (NSColor *)backgroundColor;
+ at end
+
+void foo(NSColor*);
+
+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}}
+  textField.backgroundColor = newColor; // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *', use 'colorWithCGColor:' method for this conversion}}
+  return newColor; // expected-error {{'CGColorRef' (aka 'struct CGColor *') must be explicitly converted to 'NSColor *', use 'colorWithCGColor:' method for this conversion}}
+}
+
+NSColor * Test2(NSTextField *textField, CGColorRef1 newColor) {
+  foo(newColor); // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *', define and then use a singular class method in NSColor for this conversion}}
+  textField.backgroundColor = newColor;  // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *', define and then use a singular class method in NSColor for this conversion}}
+  return newColor;  // expected-error {{'CGColorRef1' (aka 'struct CGColor1 *') must be explicitly converted to 'NSColor *', define and then use a singular class method in NSColor for this conversion}}
+}
+
+CGColorRef Test3(NSTextField *textField, CGColorRef newColor) {
+  newColor = textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'struct CGColor *'), use 'CGColor' method for this conversion}}
+  return textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef' (aka 'struct CGColor *'), use 'CGColor' method for this conversion}}
+}
+
+CGColorRef2 Test4(NSTextField *textField, CGColorRef2 newColor) {
+  newColor = textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef2' (aka 'struct CGColor2 *'), define and then use an instance method in NSColor for this conversion}}
+  return textField.backgroundColor; // expected-error {{'NSColor *' must be explicitly converted to 'CGColorRef2' (aka 'struct CGColor2 *'), define and then use an instance method in NSColor for this conversion}}
+}

Added: cfe/trunk/test/SemaObjCXX/objcbridge-related-attribute.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/objcbridge-related-attribute.mm?rev=196629&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjCXX/objcbridge-related-attribute.mm (added)
+++ cfe/trunk/test/SemaObjCXX/objcbridge-related-attribute.mm Fri Dec  6 18:34:23 2013
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fsyntax-only -x objective-c++ -verify -Wno-objc-root-class %s
+// rdar://15499111
+typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGColor))) CGColor *CGColorRef; // expected-note 6 {{declared here}}
+
+ at interface NSColor // expected-note 6 {{declared here}}
++ (NSColor *)colorWithCGColor:(CGColorRef)cgColor;
+- (CGColorRef)CGColor;
+ at end
+
+ at interface NSTextField
+- (void)setBackgroundColor:(NSColor *)color;
+- (NSColor *)backgroundColor;
+ at end
+
+
+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 *')}}
+}
+
+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 *'}}
+}
+





More information about the cfe-commits mailing list