From 4f874bf84eb3656f5361f72e317e3b4a91122354 Mon Sep 17 00:00:00 2001 From: Manman Ren Date: Fri, 6 May 2016 19:35:02 +0000 Subject: [PATCH] ObjC kindof: set the type of a conditional expression when involving kindof. When either LHS or RHS is a kindof type, we return a kindof type. rdar://problem/20513780 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@268781 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTContext.cpp | 17 +++++++++++++---- test/SemaObjC/kindof.m | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7a09b0b93b..f1aa16adba 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -7163,6 +7163,11 @@ QualType ASTContext::areCommonBaseCompatible( if (!LDecl || !RDecl) return QualType(); + // When either LHS or RHS is a kindof type, we should return a kindof type. + // For example, for common base of kindof(ASub1) and kindof(ASub2), we return + // kindof(A). + bool anyKindOf = LHS->isKindOfType() || RHS->isKindOfType(); + // Follow the left-hand side up the class hierarchy until we either hit a // root or find the RHS. Record the ancestors in case we don't find it. llvm::SmallDenseMap @@ -7197,10 +7202,12 @@ QualType ASTContext::areCommonBaseCompatible( anyChanges = true; // If anything in the LHS will have changed, build a new result type. - if (anyChanges) { + // If we need to return a kindof type but LHS is not a kindof type, we + // build a new result type. + if (anyChanges || LHS->isKindOfType() != anyKindOf) { QualType Result = getObjCInterfaceType(LHS->getInterface()); Result = getObjCObjectType(Result, LHSTypeArgs, Protocols, - LHS->isKindOfType()); + anyKindOf || LHS->isKindOfType()); return getObjCObjectPointerType(Result); } @@ -7245,10 +7252,12 @@ QualType ASTContext::areCommonBaseCompatible( if (!Protocols.empty()) anyChanges = true; - if (anyChanges) { + // If we need to return a kindof type but RHS is not a kindof type, we + // build a new result type. + if (anyChanges || RHS->isKindOfType() != anyKindOf) { QualType Result = getObjCInterfaceType(RHS->getInterface()); Result = getObjCObjectType(Result, RHSTypeArgs, Protocols, - RHS->isKindOfType()); + anyKindOf || RHS->isKindOfType()); return getObjCObjectPointerType(Result); } diff --git a/test/SemaObjC/kindof.m b/test/SemaObjC/kindof.m index 919ca960a9..aa5a0db331 100644 --- a/test/SemaObjC/kindof.m +++ b/test/SemaObjC/kindof.m @@ -187,6 +187,39 @@ void test_crosscast_conversions(void) { NSString_obj = kindof_NSNumber_obj; // expected-warning{{from '__kindof NSNumber *'}} } +@interface NSCell : NSObject +@end +@interface NSCellSub : NSCell +@end +@interface NSCellSub2 : NSCell +@end +@interface NSCellSubSub : NSCellSub +@end + +typedef signed char BOOL; +void test_conditional(BOOL flag) { + NSCellSubSub *result; + __kindof NSCellSub *kindof_Sub; + NSCell *cell; + NSCellSub *sub; + NSCellSub2 *sub2; + NSCellSubSub *subsub; + + // LHS is kindof NSCellSub, RHS is NSCell --> kindof NSCell + // LHS is kindof NSCellSub, RHS is NSCellSub --> kindof NSCellSub + // LHS is kindof NSCellSub, RHS is NSCellSub2 --> kindof NSCell + // LHS is kindof NSCellSub, RHS is NSCellSubSub --> kindof NSCellSub + result = flag ? kindof_Sub : cell; + result = flag ? kindof_Sub : sub; + result = flag ? kindof_Sub : sub2; + result = flag ? kindof_Sub : subsub; + + result = flag ? cell : kindof_Sub; + result = flag ? sub : kindof_Sub; + result = flag ? sub2 : kindof_Sub; + result = flag ? subsub : kindof_Sub; +} + // --------------------------------------------------------------------------- // Blocks // --------------------------------------------------------------------------- @@ -277,7 +310,6 @@ void test(__kindof Bar *kBar) { } // Make sure we don't emit warning about no method found. -typedef signed char BOOL; @interface A : NSObject @property (readonly, getter=isActive) BOOL active; @end -- 2.40.0