[cfe-commits] r85554 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp test/SemaObjC/conditional-expr-6.m

Fariborz Jahanian fjahanian at apple.com
Thu Oct 29 18:13:23 PDT 2009


Author: fjahanian
Date: Thu Oct 29 20:13:23 2009
New Revision: 85554

URL: http://llvm.org/viewvc/llvm-project?rev=85554&view=rev
Log:
This patch computes composite type of two objective-c expressions
used in a conditional expression by finding the most-derived common
super class of the two and qualifies the resulting type by the
intersection of the protocl qualifier list of the two objective-c
pointer types. ( this is continuation of radar 7334235).


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/test/SemaObjC/conditional-expr-6.m

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=85554&r1=85553&r2=85554&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Oct 29 20:13:23 2009
@@ -837,6 +837,8 @@
                                llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);
   unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI);
   unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD);
+  void CollectInheritedProtocols(const Decl *CDecl,
+                          llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols);
 
   //===--------------------------------------------------------------------===//
   //                            Type Operators

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=85554&r1=85553&r2=85554&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Thu Oct 29 20:13:23 2009
@@ -873,6 +873,55 @@
   }
 }
 
+/// CollectInheritedProtocols - Collect all protocols in current class and
+/// those inherited by it.
+void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
+                          llvm::SmallVectorImpl<ObjCProtocolDecl*> &Protocols) {
+  if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
+    for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
+         PE = OI->protocol_end(); P != PE; ++P) {
+      ObjCProtocolDecl *Proto = (*P);
+      Protocols.push_back(Proto);
+      for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+           PE = Proto->protocol_end(); P != PE; ++P)
+        CollectInheritedProtocols(*P, Protocols);
+      }
+    
+    // Categories of this Interface.
+    for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList(); 
+         CDeclChain; CDeclChain = CDeclChain->getNextClassCategory())
+      CollectInheritedProtocols(CDeclChain, Protocols);
+    if (ObjCInterfaceDecl *SD = OI->getSuperClass())
+      while (SD) {
+        CollectInheritedProtocols(SD, Protocols);
+        SD = SD->getSuperClass();
+      }
+    return;
+  }
+  if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
+    for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+         PE = OC->protocol_end(); P != PE; ++P) {
+      ObjCProtocolDecl *Proto = (*P);
+      Protocols.push_back(Proto);
+      for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+           PE = Proto->protocol_end(); P != PE; ++P)
+        CollectInheritedProtocols(*P, Protocols);
+    }
+    return;
+  }
+  if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) {
+    for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(),
+         PE = OP->protocol_end(); P != PE; ++P) {
+      ObjCProtocolDecl *Proto = (*P);
+      Protocols.push_back(Proto);
+      for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
+           PE = Proto->protocol_end(); P != PE; ++P)
+        CollectInheritedProtocols(*P, Protocols);
+    }
+    return;
+  }
+}
+
 unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) {
   unsigned count = 0;
   for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(),
@@ -3859,6 +3908,48 @@
   return false;
 }
 
+/// getIntersectionOfProtocols - This routine finds the intersection of set
+/// of protocols inherited from two distinct objective-c pointer objects.
+/// It is used to build composite qualifier list of the composite type of
+/// the conditional expression involving two objective-c pointer objects.
+static 
+void getIntersectionOfProtocols(ASTContext &Context,
+                                const ObjCObjectPointerType *LHSOPT,
+                                const ObjCObjectPointerType *RHSOPT,
+      llvm::SmallVectorImpl<ObjCProtocolDecl *> &IntersectionOfProtocols) {
+  
+  const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
+  const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
+  
+  llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocolSet;
+  unsigned LHSNumProtocols = LHS->getNumProtocols();
+  if (LHSNumProtocols > 0)
+    InheritedProtocolSet.insert(LHS->qual_begin(), LHS->qual_end());
+  else {
+    llvm::SmallVector<ObjCProtocolDecl *, 8> LHSInheritedProtocols;
+     Context.CollectInheritedProtocols(LHS->getDecl(), LHSInheritedProtocols);
+    InheritedProtocolSet.insert(LHSInheritedProtocols.begin(), 
+                                LHSInheritedProtocols.end());
+  }
+  
+  unsigned RHSNumProtocols = RHS->getNumProtocols();
+  if (RHSNumProtocols > 0) {
+    ObjCProtocolDecl **RHSProtocols = (ObjCProtocolDecl **)RHS->qual_begin();
+    for (unsigned i = 0; i < RHSNumProtocols; ++i)
+      if (InheritedProtocolSet.count(RHSProtocols[i]))
+        IntersectionOfProtocols.push_back(RHSProtocols[i]);
+  }
+  else {
+    llvm::SmallVector<ObjCProtocolDecl *, 8> RHSInheritedProtocols;
+    Context.CollectInheritedProtocols(RHS->getDecl(), RHSInheritedProtocols);
+    // FIXME. This may cause duplication of protocols in the list, but should
+    // be harmless.
+    for (unsigned i = 0, len = RHSInheritedProtocols.size(); i < len; ++i)
+      if (InheritedProtocolSet.count(RHSInheritedProtocols[i]))
+        IntersectionOfProtocols.push_back(RHSInheritedProtocols[i]);
+  }
+}
+
 /// areCommonBaseCompatible - Returns common base class of the two classes if
 /// one found. Note that this is O'2 algorithm. But it will be called as the
 /// last type comparison in a ?-exp of ObjC pointer types before a 
@@ -3874,8 +3965,17 @@
   while (const ObjCInterfaceDecl *LHSIDecl = LHS->getDecl()->getSuperClass()) {
     QualType LHSTy = getObjCInterfaceType(LHSIDecl);
     LHS = LHSTy->getAs<ObjCInterfaceType>();
-    if (canAssignObjCInterfaces(LHS, RHS))
-      return getObjCObjectPointerType(LHSTy);
+    if (canAssignObjCInterfaces(LHS, RHS)) {
+      llvm::SmallVector<ObjCProtocolDecl *, 8> IntersectionOfProtocols;
+      getIntersectionOfProtocols(*this, 
+                                 LHSOPT, RHSOPT, IntersectionOfProtocols);
+      if (IntersectionOfProtocols.empty())
+        LHSTy = getObjCObjectPointerType(LHSTy);
+      else
+        LHSTy = getObjCObjectPointerType(LHSTy, &IntersectionOfProtocols[0],
+                                                IntersectionOfProtocols.size());
+      return LHSTy;
+    }
   }
     
   return QualType();

Modified: cfe/trunk/test/SemaObjC/conditional-expr-6.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/conditional-expr-6.m?rev=85554&r1=85553&r2=85554&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/conditional-expr-6.m (original)
+++ cfe/trunk/test/SemaObjC/conditional-expr-6.m Thu Oct 29 20:13:23 2009
@@ -1,16 +1,24 @@
 // RUN: clang-cc -fsyntax-only -verify %s
 
+ at protocol MyProtocol @end
+
 @interface NSObject @end
 
- at interface NSInterm : NSObject
+ at interface NSInterm : NSObject <MyProtocol>
 @end
 
 @interface NSArray : NSInterm 
 @end
 
- at interface NSSet : NSObject
+ at interface NSSet : NSObject <MyProtocol>
+ at end
+
+
+ at interface N1 : NSObject
 @end
 
+ at interface N1() <MyProtocol>
+ at end
 
 NSObject* test (int argc) {
     NSArray *array = ((void*)0);
@@ -22,5 +30,22 @@
 NSObject* test1 (int argc) {
     NSArray *array = ((void*)0);
     NSSet *set = ((void*)0);
+    id <MyProtocol> instance = (argc) ? array : set;
+    id <MyProtocol> instance1 = (argc) ? set : array;
+
+    N1 *n1 = ((void*)0);
+    id <MyProtocol> instance2 = (argc) ? set : n1;
+    id <MyProtocol> instance3 = (argc) ? n1 : array;
+
+    NSArray<MyProtocol> *qual_array = ((void*)0);
+    id <MyProtocol> instance4 = (argc) ? array : qual_array;
+    id <MyProtocol> instance5 = (argc) ? qual_array : array;
+    NSSet<MyProtocol> *qual_set = ((void*)0);
+    id <MyProtocol> instance6 = (argc) ? qual_set : qual_array;
+    id <MyProtocol> instance7 = (argc) ? qual_set : array;
+    id <MyProtocol> instance8 = (argc) ? qual_array : set;
+    id <MyProtocol> instance9 = (argc) ? qual_array : qual_set;
+
+
     return (argc) ? array : set;
 }





More information about the cfe-commits mailing list