From: Daniel Dunbar Date: Tue, 26 Aug 2008 00:41:39 +0000 (+0000) Subject: In incompatible pointer-typed ?: expressions, add implicit conversion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a56f7460baf475151e03b1249a1343349328e39c;p=clang In incompatible pointer-typed ?: expressions, add implicit conversion of RHSs to id type instead of void* if either has Objective-C object type. - This ensures the result can still be used in normal places an object can be used, like a message send. Add implicit conversions for ?: applied to qualified id types to ensure that the RHSs are compatible. - This prevents a codegen crash (creating invalid PHI nodes). - Again, this relates to the fact that qualified id types have no canonical types. - Note that the implicit type casted to is incorrect, however this doesn't currently cause problems because of the flexibility of the id type. Test cases for above. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@55346 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 9a544a2e05..5169ce1311 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1248,13 +1248,21 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 Diag(questionLoc, diag::warn_typecheck_cond_incompatible_pointers, lexT.getAsString(), rexT.getAsString(), lex->getSourceRange(), rex->getSourceRange()); - // In this situation, we assume void* type. No especially good - // reason, but this is what gcc does, and we do have to pick - // to get a consistent AST. - QualType voidPtrTy = Context.getPointerType(Context.VoidTy); - ImpCastExprToType(lex, voidPtrTy); - ImpCastExprToType(rex, voidPtrTy); - return voidPtrTy; + // In this situation, assume a conservative type; in general + // we assume void* type. No especially good reason, but this + // is what gcc does, and we do have to pick to get a + // consistent AST. However, if either type is an Objective-C + // object type then use id. + QualType incompatTy; + if (Context.isObjCObjectPointerType(lexT) || + Context.isObjCObjectPointerType(rexT)) { + incompatTy = Context.getObjCIdType(); + } else { + incompatTy = Context.getPointerType(Context.VoidTy); + } + ImpCastExprToType(lex, incompatTy); + ImpCastExprToType(rex, incompatTy); + return incompatTy; } // The pointer types are compatible. // C99 6.5.15p6: If both operands are pointers to compatible types *or* to @@ -1271,10 +1279,15 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 } // Need to handle "id" explicitly. Unlike "id", whose canonical type // evaluates to "struct objc_object *" (and is handled above when comparing - // id with statically typed objects). FIXME: Do we need an ImpCastExprToType? + // id with statically typed objects). if (lexT->isObjCQualifiedIdType() || rexT->isObjCQualifiedIdType()) { - if (ObjCQualifiedIdTypesAreCompatible(lexT, rexT, true)) - return Context.getObjCIdType(); + 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, diff --git a/test/CodeGen/2008-08-25-incompatible-cond-expr.m b/test/CodeGen/2008-08-25-incompatible-cond-expr.m new file mode 100644 index 0000000000..481fe109d3 --- /dev/null +++ b/test/CodeGen/2008-08-25-incompatible-cond-expr.m @@ -0,0 +1,8 @@ +@protocol P0 +@end +@interface A +@end + +id f0(int a, id x, A* p) { + return a ? x : p; +} diff --git a/test/SemaObjC/conditional-expr2.m b/test/SemaObjC/conditional-expr2.m new file mode 100644 index 0000000000..440b72d9a2 --- /dev/null +++ b/test/SemaObjC/conditional-expr2.m @@ -0,0 +1,12 @@ +// RUN: clang -fsyntax-only -verify %s + +@interface A +@end +@interface B +@end + +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}} +}