diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-01-31 18:51:41 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-01-31 18:51:41 +0000 |
| commit | 058d3deab8924e3e1946b964745d9f0a30fd302b (patch) | |
| tree | c03693eb93aa3b07cae4f8ad8526ce0f7db75df1 /clang/test | |
| parent | e866c41f5c2f3ec7455756e4362d878866e677dd (diff) | |
| download | bcm5719-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.mm | 89 | ||||
| -rw-r--r-- | clang/test/SemaObjCXX/overload.mm | 12 |
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'}} } } |

