diff options
author | Daniel Dunbar <daniel@zuster.org> | 2008-09-03 17:53:25 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2008-09-03 17:53:25 +0000 |
commit | 40727a4b43d827319553620fa1183f4bcb346d2d (patch) | |
tree | a4b695d4a09b72e99bf4d64e80758b0147a10858 | |
parent | 60dbad831a35ba0f58256b9bcd2a085af98ff2ec (diff) |
Improve type-checking of ?: for Objective-C types.
- Allow any Objective-C object types to devolve to type id in a ?:
expression. This matches gcc behavior more closely.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55705 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 29 | ||||
-rw-r--r-- | test/SemaObjC/conditional-expr-2.m (renamed from test/SemaObjC/conditional-expr2.m) | 2 | ||||
-rw-r--r-- | test/SemaObjC/conditional-expr-3.m | 63 | ||||
-rw-r--r-- | test/SemaObjC/conditional-expr.m | 4 |
4 files changed, 83 insertions, 15 deletions
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 479c8412fd..7886976aaf 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1252,6 +1252,23 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 ImpCastExprToType(lex, rexT); // promote the null to a pointer. return rexT; } + // Allow any Objective-C types to devolve to id type. + // FIXME: This seems to match gcc behavior, although that is very + // arguably incorrect. For example, (xxx ? (id<P>) : (id<P>)) has + // type id, which seems broken. + if (Context.isObjCObjectPointerType(lexT) && + Context.isObjCObjectPointerType(rexT)) { + // FIXME: This is not the correct composite type. This only + // happens to work because id can more or less be used anywhere, + // however this may change the type of method sends. + // FIXME: gcc adds some type-checking of the arguments and emits + // (confusing) incompatible comparison warnings in some + // cases. Investigate. + QualType compositeType = Context.getObjCIdType(); + ImpCastExprToType(lex, compositeType); + ImpCastExprToType(rex, compositeType); + return compositeType; + } // Handle the case where both operands are pointers before we handle null // pointer constants in case both operands are null pointer constants. if (const PointerType *LHSPT = lexT->getAsPointerType()) { // C99 6.5.15p3,6 @@ -1312,18 +1329,6 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 return compositeType; } } - // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type - // evaluates to "struct objc_object *" (and is handled above when comparing - // id with statically typed objects). - if (lexT->isObjCQualifiedIdType() || rexT->isObjCQualifiedIdType()) { - if (ObjCQualifiedIdTypesAreCompatible(lexT, rexT, true)) { - // FIXME: This is not the correct composite type. - QualType compositeType = Context.getObjCIdType(); - ImpCastExprToType(lex, compositeType); - ImpCastExprToType(rex, compositeType); - return compositeType; - } - } // Otherwise, the operands are not compatible. Diag(questionLoc, diag::err_typecheck_cond_incompatible_operands, lexT.getAsString(), rexT.getAsString(), diff --git a/test/SemaObjC/conditional-expr2.m b/test/SemaObjC/conditional-expr-2.m index 440b72d9a2..d8a2663093 100644 --- a/test/SemaObjC/conditional-expr2.m +++ b/test/SemaObjC/conditional-expr-2.m @@ -8,5 +8,5 @@ void f0(int cond, A *a, B *b) { // Ensure that we can still send a message to result of incompatible // conditional expression. - [ (cond ? a : b) test ]; // expected-warning {{pointer type mismatch}}, expected-warning {{method '-test' not found}} + [ (cond ? a : b) test ]; // expected-warning {{method '-test' not found}} } diff --git a/test/SemaObjC/conditional-expr-3.m b/test/SemaObjC/conditional-expr-3.m new file mode 100644 index 0000000000..de7b828a98 --- /dev/null +++ b/test/SemaObjC/conditional-expr-3.m @@ -0,0 +1,63 @@ +// RUN: clang -fsyntax-only -verify %s + +@protocol P0 +@end +@protocol P1 +@end +@protocol P2 +@end + +@interface A <P0> +@end + +@interface B : A +@end + +void bar(id x); +void barP0(id<P0> x); +void barP1(id<P1> x); +void barP2(id<P2> x); + +void f0(A *a) { + id l = a; +} + +void f1(id x, A *a) { + id<P0> l = a; +} + +void f2(id<P1> x) { + id<P0> l = x; // expected-error {{incompatible type initializing 'id<P1>', expected 'id<P0>'}} +} + +void f3(A *a) { + id<P1> l = a; // expected-error {{incompatible type initializing 'A *', expected 'id<P1>'}} +} + +void f4(int cond, id x, A *a) { + bar(cond ? x : a); +} + +void f5(int cond, A *a, B *b) { + bar(cond ? a : b); +} + +void f6(int cond, id x, A *a) { + bar(cond ? (id<P0, P1>) x : a); +} + +void f7(int cond, id x, A *a) { + bar(cond ? a : (id<P0, P1>) x); +} + +void f8(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP0(cond ? x0 : x1); +} + +void f9(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP1(cond ? x0 : x1); +} + +void f10(int cond, id<P0,P1> x0, id<P0,P2> x1) { + barP2(cond ? x0 : x1); +} diff --git a/test/SemaObjC/conditional-expr.m b/test/SemaObjC/conditional-expr.m index e3cd041d3a..2884fb4c98 100644 --- a/test/SemaObjC/conditional-expr.m +++ b/test/SemaObjC/conditional-expr.m @@ -29,7 +29,7 @@ id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // GCC warns about both of these. self = nextOutputStream; // expected-error {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}} - return nextOutputStream ? nextOutputStream : self; // expected-error {{incompatible operand types ('id<DTOutputStreams>' and 'DTFilterOutputStream2 *')}} + return nextOutputStream ? nextOutputStream : self; } @end @@ -39,6 +39,6 @@ id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // GCC warns about both of these as well (no errors). self = nextOutputStream; // expected-error {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}} - return nextOutputStream ? nextOutputStream : self; // expected-error {{incompatible operand types ('id<DTOutputStreams>' and 'DTFilterOutputStream3 *')}} + return nextOutputStream ? nextOutputStream : self; } @end |