summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-31 18:51:41 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-31 18:51:41 +0000
commit058d3deab8924e3e1946b964745d9f0a30fd302b (patch)
treec03693eb93aa3b07cae4f8ad8526ce0f7db75df1 /clang/test
parente866c41f5c2f3ec7455756e4362d878866e677dd (diff)
downloadbcm5719-llvm-058d3deab8924e3e1946b964745d9f0a30fd302b.tar.gz
bcm5719-llvm-058d3deab8924e3e1946b964745d9f0a30fd302b.zip
Implement reasonable conversion ranking for Objective-C pointer
conversions (<rdar://problem/8592139>) for overload resolution. The conversion ranking mirrors C++'s conversion ranking fairly closely, except that we use a same pseudo-subtyping relationship employed by Objective-C pointer assignment rather than simple checking derived-to-base conversions. This change covers: - Conversions to pointers to a specific object type are better than conversions to 'id', 'Class', qualified 'id', or qualified 'Class' (note: GCC doesn't perform this ranking, but it matches C++'s rules for ranking conversions to void*). - Conversions to qualified 'id' or qualified 'Class' are better than conversions to 'id' or 'Class', respectively. - When two conversion sequences convert to the same type, rank the conversions based on the relationship between the types we're converting from. - When two conversion sequences convert from the same non-id, non-Class type, rank the conversions based on the relationship of the types we're converting to. (note: GCC allows this ranking even when converting from 'id', which is extremeley dangerous). llvm-svn: 124591
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/SemaObjCXX/conversion-ranking.mm89
-rw-r--r--clang/test/SemaObjCXX/overload.mm12
2 files changed, 94 insertions, 7 deletions
diff --git a/clang/test/SemaObjCXX/conversion-ranking.mm b/clang/test/SemaObjCXX/conversion-ranking.mm
new file mode 100644
index 00000000000..6c1408bf21f
--- /dev/null
+++ b/clang/test/SemaObjCXX/conversion-ranking.mm
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+@protocol P1
+@end
+
+@interface A <P1>
+@end
+
+@interface B : A
+@end
+
+@interface C : B
+@end
+
+template<typename T>
+struct ConvertsTo {
+ operator T() const;
+};
+
+
+// conversion of C* to B* is better than conversion of C* to A*.
+int &f0(A*);
+float &f0(B*);
+
+void test_f0(C *c) {
+ float &fr1 = f0(c);
+}
+
+// conversion of B* to A* is better than conversion of C* to A*
+void f1(A*);
+
+struct ConvertsToBoth {
+private:
+ operator C*() const;
+
+public:
+ operator B*() const;
+};
+
+void test_f1(ConvertsTo<B*> toB, ConvertsTo<C*> toC, ConvertsToBoth toBoth) {
+ f1(toB);
+ f1(toC);
+ f1(toBoth);
+};
+
+// A conversion to an a non-id object pointer type is better than a
+// conversion to 'id'.
+int &f2(A*);
+float &f2(id);
+
+void test_f2(B *b) {
+ int &ir = f2(b);
+}
+
+// A conversion to an a non-Class object pointer type is better than a
+// conversion to 'Class'.
+int &f3(A*);
+float &f3(Class);
+
+void test_f3(B *b) {
+ int &ir = f3(b);
+}
+
+// When both conversions convert to 'id' or 'Class', pick the most
+// specific type to convert from.
+void f4(id);
+
+void test_f4(ConvertsTo<B*> toB, ConvertsTo<C*> toC, ConvertsToBoth toBoth) {
+ f4(toB);
+ f4(toC);
+ f4(toBoth);
+}
+
+void f5(id<P1>);
+
+void test_f5(ConvertsTo<B*> toB, ConvertsTo<C*> toC, ConvertsToBoth toBoth) {
+ f5(toB);
+ f5(toC);
+ f5(toBoth);
+}
+
+
+// A conversion to an a non-id object pointer type is better than a
+// conversion to qualified 'id'.
+int &f6(A*);
+float &f6(id<P1>);
+
+void test_f6(B *b) {
+ int &ir = f6(b);
+}
diff --git a/clang/test/SemaObjCXX/overload.mm b/clang/test/SemaObjCXX/overload.mm
index 750b6b183a8..7e79a4249cb 100644
--- a/clang/test/SemaObjCXX/overload.mm
+++ b/clang/test/SemaObjCXX/overload.mm
@@ -31,8 +31,8 @@ int& f(A*); // expected-note {{candidate}}
float& f(B*); // expected-note {{candidate}}
void g(A*);
-int& h(A*); // expected-note{{candidate}}
-float& h(id); // expected-note{{candidate}}
+int& h(A*);
+float& h(id);
void test0(A* a, B* b, id val) {
int& i1 = f(a);
@@ -47,8 +47,7 @@ void test0(A* a, B* b, id val) {
int& i2 = h(a);
float& f3 = h(val);
- // FIXME: we match GCC here, but shouldn't this work?
- int& i3 = h(b); // expected-error{{call to 'h' is ambiguous}}
+ int& i3 = h(b);
}
void test1(A* a) {
@@ -114,13 +113,12 @@ namespace test5 {
}
// rdar://problem/8592139
-// FIXME: this should resolve to the unavailable candidate
namespace test6 {
- void foo(id); // expected-note {{candidate}}
+ void foo(id); // expected-note{{candidate function}}
void foo(A*) __attribute__((unavailable)); // expected-note {{explicitly made unavailable}}
void test(B *b) {
- foo(b); // expected-error {{call to 'foo' is ambiguous}}
+ foo(b); // expected-error {{call to unavailable function 'foo'}}
}
}
OpenPOWER on IntegriCloud