From a119a3b07372888a2f5b9ec693c52daae7c0f522 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 18 Feb 2009 04:38:20 +0000 Subject: [PATCH] fix rdar://6597252: two exactly identical pointer types are always compatible, even if they are weird implicit objc pointer types like Class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64885 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExpr.cpp | 22 +++++++++++++++------- test/SemaObjC/exprs.m | 7 +++++++ 2 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 test/SemaObjC/exprs.m diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3b80cd0132..4eb29c4f94 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2218,8 +2218,9 @@ Sema::ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, /// Note that lex is not null here, even if this is the gnu "x ?: y" extension. /// In that case, lex = cond. -inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 - Expr *&Cond, Expr *&LHS, Expr *&RHS, SourceLocation QuestionLoc) { +/// C99 6.5.15 +QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, + SourceLocation QuestionLoc) { UsualUnaryConversions(Cond); UsualUnaryConversions(LHS); UsualUnaryConversions(RHS); @@ -2284,6 +2285,7 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. return RHSTy; } + // 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 = LHSTy->getAsPointerType()) { // C99 6.5.15p3,6 @@ -2310,6 +2312,11 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 return destType; } + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical pointers types are always compatible. + return LHSTy; + } + QualType compositeType = LHSTy; // If either type is an Objective-C object type then check @@ -2373,6 +2380,12 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 return compositeType; } } + + // Selection between block pointer types is ok as long as they are the same. + if (LHSTy->isBlockPointerType() && RHSTy->isBlockPointerType() && + Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) + return LHSTy; + // 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). @@ -2398,11 +2411,6 @@ inline QualType Sema::CheckConditionalOperands( // C99 6.5.15 } } - // Selection between block pointer types is ok as long as they are the same. - if (LHSTy->isBlockPointerType() && RHSTy->isBlockPointerType() && - Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) - return LHSTy; - // Otherwise, the operands are not compatible. Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); diff --git a/test/SemaObjC/exprs.m b/test/SemaObjC/exprs.m new file mode 100644 index 0000000000..d675865eb5 --- /dev/null +++ b/test/SemaObjC/exprs.m @@ -0,0 +1,7 @@ +// RUN: clang %s -fsyntax-only + +// rdar://6597252 +Class foo(Class X) { + return 1 ? X : X; +} + -- 2.40.0