Teach the ARC compiler to not require __bridge casts when
passing/receiving CF objects at +0 to/from Objective-C methods
or audited C functions.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142219 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/ARCMT/checking.m b/test/ARCMT/checking.m
index 7c24dc4..0e441cb 100644
--- a/test/ARCMT/checking.m
+++ b/test/ARCMT/checking.m
@@ -62,8 +62,8 @@
 
   CFStringRef cfstr;
   NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' 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 'CFStringRef' (aka 'const struct __CFString *') into ARC}}
+  // expected-note {{use __bridge to convert directly (no change in ownership)}} \
+  // expected-note {{use __bridge_transfer to transfer ownership of a +1 'CFStringRef' (aka 'const struct __CFString *') into ARC}} \
   str = (NSString *)kUTTypePlainText;
   str = b ? kUTTypeRTF : kUTTypePlainText;
   str = (NSString *)(b ? kUTTypeRTF : kUTTypePlainText);
@@ -120,11 +120,11 @@
   (void)(__autoreleasing id**)voidp_val;
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{disallowed}}
-  cvt((void*)arg); // expected-error {{requires a bridged cast}} expected-error {{disallowed}} \
-                   // expected-note {{use __bridge}} expected-note {{use __bridge_retained}} 
+  cvt((void*)arg); // expected-error 2 {{requires a bridged cast}} \
+                   // expected-note 2 {{use __bridge to}} expected-note {{use __bridge_transfer}} expected-note {{use __bridge_retained}}
   cvt(0);
   (void)(__strong id**)(0);
-  return arg; // expected-error {{disallowed}}
+  return arg; // expected-error {{requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_retained}}
 }
 
 
diff --git a/test/ARCMT/nonobjc-to-objc-cast-2.m b/test/ARCMT/nonobjc-to-objc-cast-2.m
index 5dba61f..2900b9a 100644
--- a/test/ARCMT/nonobjc-to-objc-cast-2.m
+++ b/test/ARCMT/nonobjc-to-objc-cast-2.m
@@ -14,7 +14,7 @@
   NSString *str = (NSString *)cfstr; // expected-error {{cast of C pointer type 'CFStringRef' (aka 'const struct __CFString *') to Objective-C pointer type 'NSString *' 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 'CFStringRef' (aka 'const struct __CFString *') into ARC}}
-  void *vp = str;  // expected-error {{disallowed}}
+  void *vp = str;  // expected-error {{requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge}}
 }
 
 void f2(NSString *s) {
diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
index d2a23ce..1bd0d34 100644
--- a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
+++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp
@@ -165,8 +165,8 @@
     { bool b = &S::f<char>; }
     { bool b = &S::f<int>; }
     // These next two errors are terrible.
-    { bool b = s.f<char>; } // expected-error {{cannot initialize}}
-    { bool b = s.f<int>; } // expected-error {{cannot initialize}}
+    { bool b = s.f<char>; } // expected-error {{reference to non-static member function must be called}}
+    { bool b = s.f<int>; } // expected-error {{reference to non-static member function must be called}}
     { bool b = &s.f<char>; } // expected-error {{cannot create a non-constant pointer to member function}}
     { bool b = &s.f<int>; } // expected-error {{cannot create a non-constant pointer to member function}}
 
diff --git a/test/SemaCXX/addr-of-overloaded-function.cpp b/test/SemaCXX/addr-of-overloaded-function.cpp
index a36fd58..c3360cc 100644
--- a/test/SemaCXX/addr-of-overloaded-function.cpp
+++ b/test/SemaCXX/addr-of-overloaded-function.cpp
@@ -57,8 +57,7 @@
 
 struct C {
   C &getC() {
-    // FIXME: this error message is terrible
-    return makeAC; // expected-error{{cannot bind to a value of unrelated type}}
+    return makeAC; // expected-error{{reference to non-static member function must be called}}
   }
 
   C &makeAC();
diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp
index cf64810..4e8b4a8 100644
--- a/test/SemaCXX/member-pointer.cpp
+++ b/test/SemaCXX/member-pointer.cpp
@@ -278,7 +278,7 @@
     typedef R T::*F;
     F f_;
     template<class U> int & call(U u)
-    { return u->*f_; } // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type '<bound member function type>'}}
+    { return u->*f_; } // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
 
     template<class U> int operator()(U u)
     { call(u); } // expected-note{{in instantiation of}}
diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp
index a5ec51c..6da0354 100644
--- a/test/SemaCXX/overloaded-name.cpp
+++ b/test/SemaCXX/overloaded-name.cpp
@@ -21,11 +21,10 @@
   public:
     const char* text(void);
     void g(void) {
-      // FIXME: why 2x?
       f(text());
-      f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
       f(text());
-      f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
+      f(text); // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
     }
   };
 }
diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp
index 1e4a3b7..d9b75f7 100644
--- a/test/SemaCXX/overloaded-operator.cpp
+++ b/test/SemaCXX/overloaded-operator.cpp
@@ -392,7 +392,7 @@
   };
 
   struct Y {
-    Y &operator<<(int); // expected-note{{candidate function not viable: no known conversion from '<bound member function type>' to 'int'}}
+    Y &operator<<(int);
   };
 
   void f(X x, Y y) {
diff --git a/test/SemaCXX/unknown-anytype.cpp b/test/SemaCXX/unknown-anytype.cpp
index ba52122..a07ec83 100644
--- a/test/SemaCXX/unknown-anytype.cpp
+++ b/test/SemaCXX/unknown-anytype.cpp
@@ -14,9 +14,9 @@
     // making sure that these locations check for placeholder types
     // properly.
 
-    int x = foo; // expected-error {{cannot initialize}}
+    int x = foo; // expected-error {{'foo' has unknown type}}
     int y = 0 + foo; // expected-error {{'foo' has unknown type}}
-    return foo; // expected-error {{cannot initialize}}
+    return foo; // expected-error {{'foo' has unknown type}}
   }
 }
 
diff --git a/test/SemaObjC/arc-type-conversion.m b/test/SemaObjC/arc-type-conversion.m
index 01f61bd..c626ced 100644
--- a/test/SemaObjC/arc-type-conversion.m
+++ b/test/SemaObjC/arc-type-conversion.m
@@ -12,12 +12,15 @@
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{cast of an Objective-C pointer to 'void **' is disallowed with ARC}}
   cvt((void*)arg); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \
-                   // expected-error {{implicit conversion of a non-Objective-C pointer type 'void *' to 'id' is disallowed with ARC}} \
-                   // 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 'void *'}}
+                   // expected-error {{implicit conversion of C pointer type 'void *' to Objective-C pointer type 'id' requires a bridged cast}} \
+                   // expected-note 2 {{use __bridge to convert directly (no change in ownership)}} \
+                   // expected-note {{use __bridge_retained to make an ARC object available as a +1 'void *'}} \
+                   // expected-note {{use __bridge_transfer to transfer ownership of a +1 'void *' into ARC}}
   cvt(0);
   (void)(__strong id**)(0);
-  return arg; // expected-error {{implicit conversion of an Objective-C pointer to 'void *' is disallowed with ARC}}
+  return arg; // expected-error {{implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' 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 'void *'}}
 }
 
 void to_void(__strong id *sip, __weak id *wip,
diff --git a/test/SemaObjC/arc-unbridged-cast.m b/test/SemaObjC/arc-unbridged-cast.m
index 8b835a1..2a8a24d 100644
--- a/test/SemaObjC/arc-unbridged-cast.m
+++ b/test/SemaObjC/arc-unbridged-cast.m
@@ -70,3 +70,50 @@
   x = (id) (cond ? (void*) 0 : [object newString]);
   x = (id) (cond ? (CFStringRef) @"help" : [object newString]); // a bit questionable
 }
+
+// rdar://problem/10246264
+@interface CFTaker
+- (void) takeOrdinary: (CFStringRef) arg;
+- (void) takeVariadic: (int) n, ...;
+- (void) takeConsumed: (CFStringRef __attribute__((cf_consumed))) arg;
+@end
+void testCFTaker(CFTaker *taker, id string) {
+  [taker takeOrdinary: (CFStringRef) string];
+  [taker takeVariadic: 1, (CFStringRef) string];
+  [taker takeConsumed: (CFStringRef) string]; // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void takeCFOrdinaryUnaudited(CFStringRef arg);
+void takeCFVariadicUnaudited(int n, ...);
+void takeCFConsumedUnaudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited begin
+void takeCFOrdinaryAudited(CFStringRef arg);
+void takeCFVariadicAudited(int n, ...);
+void takeCFConsumedAudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited end
+
+void testTakerFunctions(id string) {
+  takeCFOrdinaryUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, (CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited((CFStringRef) string);
+  takeCFVariadicAudited(1, (CFStringRef) string);
+  takeCFConsumedAudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void testTakerFunctions_parens(id string) {
+  takeCFOrdinaryUnaudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, ((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited(((CFStringRef) string));
+  takeCFVariadicAudited(1, ((CFStringRef) string));
+  takeCFConsumedAudited(((CFStringRef) string)); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index ed6e60d..3f4c406 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -263,8 +263,8 @@
   b = (vp == nil);
   b = (nil == vp);
 
-  b = (vp == op); // expected-error {{implicit conversion of an Objective-C pointer to 'void *'}}
-  b = (op == vp); // expected-error {{implicit conversion of a non-Objective-C pointer type 'void *' to 'id'}}
+  b = (vp == op); // expected-error {{implicit conversion of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_retained}}
+  b = (op == vp); // expected-error {{implicit conversion of C pointer type 'void *' to Objective-C pointer type 'id' requires a bridged cast}} expected-note {{use __bridge}} expected-note {{use __bridge_transfer}}
 }
 
 void test12(id collection) {
diff --git a/test/SemaObjCXX/arc-type-conversion.mm b/test/SemaObjCXX/arc-type-conversion.mm
index 48d1e48..fd42513 100644
--- a/test/SemaObjCXX/arc-type-conversion.mm
+++ b/test/SemaObjCXX/arc-type-conversion.mm
@@ -12,10 +12,7 @@
   (void)(__autoreleasing id**)voidp_val;
   (void)(void*)voidp_val;
   (void)(void**)arg; // expected-error {{cast of an Objective-C pointer to 'void **' is disallowed}}
-  cvt((void*)arg); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'void *' requires a bridged cast}} \
-                   // expected-error {{no matching function for call to 'cvt'}} \
-  // 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 'void *'}}
+  cvt((void*)arg); // expected-error {{no matching function for call to 'cvt'}}
   cvt(0);
   (void)(__strong id**)(0);
 
diff --git a/test/SemaObjCXX/arc-unbridged-cast.mm b/test/SemaObjCXX/arc-unbridged-cast.mm
new file mode 100644
index 0000000..81f3291
--- /dev/null
+++ b/test/SemaObjCXX/arc-unbridged-cast.mm
@@ -0,0 +1,106 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -fobjc-arc -verify %s
+
+typedef const struct __CFString * CFStringRef;
+
+@interface Object
+@property CFStringRef property;
+- (CFStringRef) implicitProperty;
+- (CFStringRef) newString;
+- (CFStringRef) makeString;
+@end
+
+extern Object *object;
+
+// rdar://9744349
+id test0(void) {
+  id p1 = (id)[object property];
+  id p2 = (__bridge_transfer id)[object property];
+  id p3 = (__bridge id)[object property];
+  return (id) object.property;
+}
+
+// rdar://10140692
+CFStringRef unauditedString(void);
+CFStringRef plusOneString(void) __attribute__((cf_returns_retained));
+
+#pragma clang arc_cf_code_audited begin
+CFStringRef auditedString(void);
+CFStringRef auditedCreateString(void);
+#pragma clang arc_cf_code_audited end
+
+void test1(int cond) {
+  id x;
+  x = (id) auditedString();
+  x = (id) (cond ? auditedString() : (void*) 0);
+  x = (id) (cond ? (void*) 0 : auditedString());
+  x = (id) (cond ? (CFStringRef) @"help" : auditedString());
+
+  x = (id) unauditedString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? unauditedString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (void*) 0 : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (CFStringRef) @"help" : unauditedString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+
+  x = (id) auditedCreateString(); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? auditedCreateString() : (void*) 0); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (void*) 0 : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+  x = (id) (cond ? (CFStringRef) @"help" : auditedCreateString()); // expected-error {{requires a bridged cast}} expected-note {{use __bridge to}} expected-note {{use __bridge_transfer to}}
+
+  x = (id) [object property];
+  x = (id) (cond ? [object property] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object property]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object property]);  
+
+  x = (id) object.property;
+  x = (id) (cond ? object.property : (void*) 0);
+  x = (id) (cond ? (void*) 0 : object.property);
+  x = (id) (cond ? (CFStringRef) @"help" : object.property);  
+
+  x = (id) object.implicitProperty;
+  x = (id) (cond ? object.implicitProperty : (void*) 0);
+  x = (id) (cond ? (void*) 0 : object.implicitProperty);
+  x = (id) (cond ? (CFStringRef) @"help" : object.implicitProperty);  
+
+  x = (id) [object makeString];
+  x = (id) (cond ? [object makeString] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object makeString]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object makeString]);  
+
+  x = (id) [object newString];
+  x = (id) (cond ? [object newString] : (void*) 0);
+  x = (id) (cond ? (void*) 0 : [object newString]);
+  x = (id) (cond ? (CFStringRef) @"help" : [object newString]); // a bit questionable
+}
+
+// rdar://problem/10246264
+@interface CFTaker
+- (void) takeOrdinary: (CFStringRef) arg;
+- (void) takeVariadic: (int) n, ...;
+- (void) takeConsumed: (CFStringRef __attribute__((cf_consumed))) arg;
+@end
+void testCFTaker(CFTaker *taker, id string) {
+  [taker takeOrdinary: (CFStringRef) string];
+  [taker takeVariadic: 1, (CFStringRef) string];
+  [taker takeConsumed: (CFStringRef) string]; // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}
+
+void takeCFOrdinaryUnaudited(CFStringRef arg);
+void takeCFVariadicUnaudited(int n, ...);
+void takeCFConsumedUnaudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited begin
+void takeCFOrdinaryAudited(CFStringRef arg);
+void takeCFVariadicAudited(int n, ...);
+void takeCFConsumedAudited(CFStringRef __attribute__((cf_consumed)) arg);
+#pragma clang arc_cf_code_audited end
+
+void testTakerFunctions(id string) {
+  takeCFOrdinaryUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFVariadicUnaudited(1, (CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+  takeCFConsumedUnaudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  void (*taker)(CFStringRef) = 0;
+  taker((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+
+  takeCFOrdinaryAudited((CFStringRef) string);
+  takeCFVariadicAudited(1, (CFStringRef) string);
+  takeCFConsumedAudited((CFStringRef) string); // expected-error {{cast of Objective-C pointer type 'id' to C pointer type 'CFStringRef'}} expected-note {{use __bridge to}} expected-note {{use __bridge_retained to}}
+}