[cfe-commits] r75808 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Frontend/PCHBitCodes.h lib/AST/ASTContext.cpp lib/AST/Type.cpp lib/CodeGen/CodeGenTypes.cpp lib/CodeGen/Mangle.cpp lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaOverload.cpp test/SemaObjC/comptypes-3.m test/SemaObjC/conditional-expr-3.m

Steve Naroff snaroff at apple.com
Wed Jul 15 11:40:40 PDT 2009


Author: snaroff
Date: Wed Jul 15 13:40:39 2009
New Revision: 75808

URL: http://llvm.org/viewvc/llvm-project?rev=75808&view=rev
Log:
Implement the ObjC pseudo built-in types as clang "BuiltinType's". I say pseudo built-in types, since Sema still injects a typedef for recognition (i.e. they aren't truly built-ins from a parser perspective).

This removes the static data/methods on ObjCObjectPointerType while preserving the nice API (no need to fiddle with ASTContext:-).

This patch also adds Type::isObjCBuiltinType().

This should be the last fairly large patch related to recrafting the ObjC type system. The follow-on patches should be fairly small.

Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
    cfe/trunk/lib/CodeGen/Mangle.cpp
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/test/SemaObjC/comptypes-3.m
    cfe/trunk/test/SemaObjC/conditional-expr-3.m

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

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Jul 15 13:40:39 2009
@@ -106,7 +106,7 @@
   QualType BuiltinVaListType;
 
   /// ObjCIdType - a pseudo built-in typedef type (set by Sema).
-  QualType ObjCIdType;
+  QualType ObjCIdTypedefType;
   
   /// ObjCSelType - another pseudo built-in typedef type (set by Sema).
   QualType ObjCSelType;
@@ -117,7 +117,7 @@
   const RecordType *ProtoStructType;
 
   /// ObjCClassType - another pseudo built-in typedef type (set by Sema).
-  QualType ObjCClassType;
+  QualType ObjCClassTypedefType;
   
   QualType ObjCConstantStringType;
   RecordDecl *CFConstantStringTypeDecl;
@@ -210,6 +210,7 @@
   QualType OverloadTy;
   QualType DependentTy;
   QualType UndeducedAutoTy;
+  QualType ObjCBuiltinIdTy, ObjCBuiltinClassTy;
 
   ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t,
              IdentifierTable &idents, SelectorTable &sels,
@@ -490,7 +491,7 @@
 
   /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by
   /// Sema.  id is always a (typedef for a) pointer type, a pointer to a struct.
-  QualType getObjCIdType() const { return ObjCIdType; }
+  QualType getObjCIdType() const { return ObjCIdTypedefType; }
   void setObjCIdType(QualType T);
   
   void setObjCSelType(QualType T);
@@ -502,7 +503,7 @@
   /// This setter/getter repreents the ObjC 'Class' type. It is setup lazily, by
   /// Sema.  'Class' is always a (typedef for a) pointer type, a pointer to a
   /// struct.
-  QualType getObjCClassType() const { return ObjCClassType; }
+  QualType getObjCClassType() const { return ObjCClassTypedefType; }
   void setObjCClassType(QualType T);
   
   void setBuiltinVaListType(QualType T);
@@ -768,10 +769,10 @@
   bool typesAreCompatible(QualType, QualType); // C99 6.2.7p1
   
   bool isObjCIdType(QualType T) const {
-    return T == ObjCIdType;
+    return T == ObjCIdTypedefType;
   }
   bool isObjCClassType(QualType T) const {
-    return T == ObjCClassType;
+    return T == ObjCClassTypedefType;
   }
   bool isObjCSelType(QualType T) const {
     assert(SelStructType && "isObjCSelType used before 'SEL' type is built");

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

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Jul 15 13:40:39 2009
@@ -404,6 +404,7 @@
   bool isObjCQualifiedIdType() const;           // id<foo>
   bool isObjCIdType() const;                    // id
   bool isObjCClassType() const;                 // Class
+  bool isObjCBuiltinType() const;               // 'id' or 'Class'
   bool isTemplateTypeParmType() const;          // C++ template type parameter
   bool isNullPtrType() const;                   // C++0x nullptr_t
 
@@ -592,8 +593,10 @@
     Overload,  // This represents the type of an overloaded function declaration.
     Dependent, // This represents the type of a type-dependent expression.
     
-    UndeducedAuto  // In C++0x, this represents the type of an auto variable
+    UndeducedAuto, // In C++0x, this represents the type of an auto variable
                    // that has not been deduced yet.
+    ObjCId,    // This represents the ObjC 'id' type.
+    ObjCClass  // This represents the ObjC 'Class' type.
   };
 private:
   Kind TypeKind;
@@ -1899,7 +1902,7 @@
 /// Duplicate protocols are removed and protocol list is canonicalized to be in
 /// alphabetical order.
 class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
-  QualType PointeeType; // will always point to an interface type.
+  QualType PointeeType; // A builin or interface type.
   
   // List of protocols for this protocol conforming object type
   // List is sorted on protocol name. No protocol is entered more than once.
@@ -1909,20 +1912,10 @@
     Type(ObjCObjectPointer, QualType(), /*Dependent=*/false),
     PointeeType(T), Protocols(Protos, Protos+NumP) { }
   friend class ASTContext;  // ASTContext creates these.
-  friend class ObjCInterfaceType; // To enable 'id' and 'Class' predicates.
   
-  static ObjCInterfaceType *IdInterfaceT;
-  static ObjCInterfaceType *ClassInterfaceT;
-  static void setIdInterface(QualType T) { 
-    IdInterfaceT =  dyn_cast<ObjCInterfaceType>(T.getTypePtr()); 
-  }
-  static void setClassInterface(QualType T) { 
-    ClassInterfaceT =  dyn_cast<ObjCInterfaceType>(T.getTypePtr()); 
-  }
-  static ObjCInterfaceType *getIdInterface() { return IdInterfaceT; }
-  static ObjCInterfaceType *getClassInterface() { return ClassInterfaceT; }
 public:
-  // Get the pointee type. Pointee is required to always be an interface type.
+  // Get the pointee type. Pointee will either be a built-in type (for 'id' and
+  // 'Class') or will be an interface type (for user-defined types).
   // Note: Pointee can be a TypedefType whose canonical type is an interface. 
   // Example: typedef NSObject T; T *var;
   QualType getPointeeType() const { return PointeeType; }
@@ -1930,18 +1923,29 @@
   const ObjCInterfaceType *getInterfaceType() const { 
     return PointeeType->getAsObjCInterfaceType(); 
   }
+  /// getInterfaceDecl - returns an interface decl for user-defined types.
   ObjCInterfaceDecl *getInterfaceDecl() const {
-    return getInterfaceType()->getDecl();
-  }
-  /// isObjCQualifiedIdType - true for "id <p>".
-  bool isObjCQualifiedIdType() const { 
-    return getInterfaceType() == IdInterfaceT && Protocols.size(); 
+    return getInterfaceType() ? getInterfaceType()->getDecl() : 0;
   }
+  /// isObjCIdType - true for "id".
   bool isObjCIdType() const {
-    return getInterfaceType() == IdInterfaceT && !Protocols.size();
+    return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && 
+           !Protocols.size();
   }
+  /// isObjCClassType - true for "Class".
   bool isObjCClassType() const {
-    return getInterfaceType() == ClassInterfaceT && !Protocols.size();
+    return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && 
+           !Protocols.size();
+  }
+  /// isObjCQualifiedIdType - true for "id <p>".
+  bool isObjCQualifiedIdType() const { 
+    return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && 
+           Protocols.size(); 
+  }
+  /// isObjCQualifiedClassType - true for "Class <p>".
+  bool isQualifiedClassType() const {
+    return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCClass) && 
+           Protocols.size();
   }
   /// qual_iterator and friends: this provides access to the (potentially empty)
   /// list of protocols qualifying this interface.
@@ -2188,23 +2192,24 @@
   return isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType());
 }
 inline bool Type::isObjCQualifiedIdType() const {
-  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
     return OPT->isObjCQualifiedIdType();
-  }
   return false;
 }
 inline bool Type::isObjCIdType() const {
-  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
     return OPT->isObjCIdType();
-  }
   return false;
 }
 inline bool Type::isObjCClassType() const {
-  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType()) {
+  if (const ObjCObjectPointerType *OPT = getAsObjCObjectPointerType())
     return OPT->isObjCClassType();
-  }
   return false;
 }
+inline bool Type::isObjCBuiltinType() const {
+  return isObjCIdType() || isObjCClassType();
+}
+
 inline bool Type::isTemplateTypeParmType() const {
   return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType());
 }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Jul 15 13:40:39 2009
@@ -1457,8 +1457,6 @@
   "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
 def warn_incompatible_qualified_id : Warning<
   "incompatible type %2 %1, expected %0">;
-def warn_incompatible_qualified_id_operands : Warning<
-  "invalid operands to binary expression (%0 and %1)">;
 def ext_typecheck_convert_pointer_int : ExtWarn<
   "incompatible pointer to integer conversion %2 %1, expected %0">;
 def ext_typecheck_convert_int_pointer : ExtWarn<

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Wed Jul 15 13:40:39 2009
@@ -333,7 +333,11 @@
       /// \brief The C++ 'char16_t' type.
       PREDEF_TYPE_CHAR16_ID     = 24,
       /// \brief The C++ 'char32_t' type.
-      PREDEF_TYPE_CHAR32_ID     = 25
+      PREDEF_TYPE_CHAR32_ID     = 25,
+      /// \brief The ObjC 'id' type.
+      PREDEF_TYPE_OBJC_ID       = 26,
+      /// \brief The ObjC 'Class' type.
+      PREDEF_TYPE_OBJC_CLASS    = 27     
     };
 
     /// \brief The number of predefined type IDs that are reserved for

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

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jul 15 13:40:39 2009
@@ -201,8 +201,13 @@
 
   BuiltinVaListType = QualType();
   
-  ObjCIdType = QualType();
-  ObjCClassType = QualType();
+  // "Builtin" typedefs set by Sema::ActOnTranslationUnitScope().
+  ObjCIdTypedefType = QualType();
+  ObjCClassTypedefType = QualType();
+  
+  // Builtin types for 'id' and 'Class'.
+  InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId);
+  InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass);
 
   ObjCConstantStringType = QualType();
   
@@ -1868,7 +1873,7 @@
                                               ObjCProtocolDecl **Protocols, 
                                               unsigned NumProtocols) {
   if (InterfaceT.isNull()) 
-    InterfaceT = QualType(ObjCObjectPointerType::getIdInterface(), 0);
+    InterfaceT = ObjCBuiltinIdTy;
     
   // Sort the protocol list alphabetically to canonicalize it.
   if (NumProtocols)
@@ -2471,7 +2476,7 @@
     
     QualType FieldTypes[] = {
       UnsignedLongTy,
-      getPointerType(ObjCIdType),
+      getPointerType(ObjCIdTypedefType),
       getPointerType(UnsignedLongTy),
       getConstantArrayType(UnsignedLongTy,
                            llvm::APInt(32, 5), ArrayType::Normal, 0)
@@ -3018,13 +3023,7 @@
 }
 
 void ASTContext::setObjCIdType(QualType T) {
-  ObjCIdType = T;
-  const TypedefType *TT = T->getAsTypedefType();
-  assert(TT && "missing 'id' typedef");
-  const ObjCObjectPointerType *OPT = 
-    TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
-  assert(OPT && "missing 'id' type");
-  ObjCObjectPointerType::setIdInterface(OPT->getPointeeType());
+  ObjCIdTypedefType = T;
 }
 
 void ASTContext::setObjCSelType(QualType T) {
@@ -3050,13 +3049,7 @@
 }
 
 void ASTContext::setObjCClassType(QualType T) {
-  ObjCClassType = T;
-  const TypedefType *TT = T->getAsTypedefType();
-  assert(TT && "missing 'Class' typedef");
-  const ObjCObjectPointerType *OPT = 
-    TT->getDecl()->getUnderlyingType()->getAsObjCObjectPointerType();
-  assert(OPT && "missing 'Class' type");
-  ObjCObjectPointerType::setClassInterface(OPT->getPointeeType());
+  ObjCClassTypedefType = T;
 }
 
 void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) {
@@ -3235,27 +3228,38 @@
 /// FIXME: Move the following to ObjCObjectPointerType/ObjCInterfaceType.
 bool ASTContext::canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT,
                                          const ObjCObjectPointerType *RHSOPT) {
-  // If either interface represents the built-in 'id' or 'Class' types, 
-  // then return true (no need to call canAssignObjCInterfaces()).
-  if (LHSOPT->isObjCIdType() || RHSOPT->isObjCIdType() ||
-      LHSOPT->isObjCClassType() || RHSOPT->isObjCClassType())
+  // If either type represents the built-in 'id' or 'Class' types, return true.
+  if (LHSOPT->isObjCBuiltinType() || RHSOPT->isObjCBuiltinType())
     return true;
 
   const ObjCInterfaceType* LHS = LHSOPT->getInterfaceType();
   const ObjCInterfaceType* RHS = RHSOPT->getInterfaceType();
-  if (!LHS || !RHS)
-    return false;
+  if (!LHS || !RHS) {
+    // We have qualified builtin types.
+    // Both the right and left sides have qualifiers.    
+    for (ObjCObjectPointerType::qual_iterator I = LHSOPT->qual_begin(),
+         E = LHSOPT->qual_end(); I != E; ++I) {
+      bool RHSImplementsProtocol = false;
+
+      // when comparing an id<P> on lhs with a static type on rhs,
+      // see if static class implements all of id's protocols, directly or
+      // through its super class and categories.
+      for (ObjCObjectPointerType::qual_iterator J = RHSOPT->qual_begin(),
+           E = RHSOPT->qual_end(); J != E; ++J) {
+        if ((*J)->lookupProtocolNamed((*I)->getIdentifier()))
+          RHSImplementsProtocol = true;
+      }
+      if (!RHSImplementsProtocol)
+        return false;
+    }
+    // The RHS implements all protocols listed on the LHS.
+    return true;
+  }
   return canAssignObjCInterfaces(LHS, RHS);
 }
 
 bool ASTContext::canAssignObjCInterfaces(const ObjCInterfaceType *LHS,
                                          const ObjCInterfaceType *RHS) {
-  // If either interface represents the built-in 'id' or 'Class' types, 
-  // then return true.
-  if (LHS->isObjCIdInterface() || RHS->isObjCIdInterface() ||
-      LHS->isObjCClassInterface() || RHS->isObjCClassInterface())
-    return true;
-
   // Verify that the base decls are compatible: the RHS must be a subclass of
   // the LHS.
   if (!LHS->getDecl()->isSuperClassOf(RHS->getDecl()))

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

==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Jul 15 13:40:39 2009
@@ -22,9 +22,6 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace clang;
 
-ObjCInterfaceType *ObjCObjectPointerType::IdInterfaceT;
-ObjCInterfaceType *ObjCObjectPointerType::ClassInterfaceT;
-
 bool QualType::isConstant(ASTContext &Ctx) const {
   if (isConstQualified())
     return true;
@@ -1009,6 +1006,8 @@
   case Overload:          return "<overloaded function type>";
   case Dependent:         return "<dependent type>";
   case UndeducedAuto:     return "auto";
+  case ObjCId:            return "id";
+  case ObjCClass:         return "Class";
   }
 }
 
@@ -1687,14 +1686,6 @@
     InnerString = MyString + ' ' + InnerString;
 }
 
-bool ObjCInterfaceType::isObjCIdInterface() const {
-  return this == ObjCObjectPointerType::getIdInterface();
-}
-
-bool ObjCInterfaceType::isObjCClassInterface() const {
-  return this == ObjCObjectPointerType::getClassInterface();
-}  
-
 void ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {
   if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.
     InnerString = ' ' + InnerString;
@@ -1703,7 +1694,14 @@
 
 void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString, 
                                                 const PrintingPolicy &Policy) const {
-  std::string ObjCQIString = getInterfaceType()->getDecl()->getNameAsString();
+  std::string ObjCQIString;
+  
+  if (isObjCIdType() || isObjCQualifiedIdType())
+    ObjCQIString = "id";
+  else if (isObjCClassType())
+    ObjCQIString = "Class";
+  else
+    ObjCQIString = getInterfaceDecl()->getNameAsString();
 
   if (!qual_empty()) {
     ObjCQIString += '<';

Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenTypes.cpp Wed Jul 15 13:40:39 2009
@@ -228,6 +228,8 @@
     switch (cast<BuiltinType>(Ty).getKind()) {
     default: assert(0 && "Unknown builtin type!");
     case BuiltinType::Void:
+    case BuiltinType::ObjCId:
+    case BuiltinType::ObjCClass:
       // LLVM void type can only be used as the result of a function call.  Just
       // map to the same as char.
       return llvm::IntegerType::get(8);

Modified: cfe/trunk/lib/CodeGen/Mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/Mangle.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/Mangle.cpp (original)
+++ cfe/trunk/lib/CodeGen/Mangle.cpp Wed Jul 15 13:40:39 2009
@@ -577,6 +577,8 @@
   case BuiltinType::UndeducedAuto:
     assert(0 && "Should not see undeduced auto here");
     break;
+  case BuiltinType::ObjCId: Out << "2id"; break;
+  case BuiltinType::ObjCClass: Out << "5Class"; break;
   }
 }
 

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Wed Jul 15 13:40:39 2009
@@ -1986,6 +1986,8 @@
     case pch::PREDEF_TYPE_NULLPTR_ID:    T = Context->NullPtrTy;          break;
     case pch::PREDEF_TYPE_CHAR16_ID:     T = Context->Char16Ty;           break;
     case pch::PREDEF_TYPE_CHAR32_ID:     T = Context->Char32Ty;           break;
+    case pch::PREDEF_TYPE_OBJC_ID:       T = Context->ObjCBuiltinIdTy;    break;
+    case pch::PREDEF_TYPE_OBJC_CLASS:    T = Context->ObjCBuiltinClassTy; break;
     }
 
     assert(!T.isNull() && "Unknown predefined type");

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Wed Jul 15 13:40:39 2009
@@ -2009,6 +2009,8 @@
     case BuiltinType::Char32:     ID = pch::PREDEF_TYPE_CHAR32_ID;     break;
     case BuiltinType::Overload:   ID = pch::PREDEF_TYPE_OVERLOAD_ID;   break;
     case BuiltinType::Dependent:  ID = pch::PREDEF_TYPE_DEPENDENT_ID;  break;
+    case BuiltinType::ObjCId:     ID = pch::PREDEF_TYPE_OBJC_ID;       break;
+    case BuiltinType::ObjCClass:  ID = pch::PREDEF_TYPE_OBJC_CLASS;    break;
     case BuiltinType::UndeducedAuto:
       assert(0 && "Should not see undeduced auto here");
       break;

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Jul 15 13:40:39 2009
@@ -149,35 +149,23 @@
     Context.setObjCProtoType(Context.getObjCInterfaceType(ProtocolDecl));
     PushOnScopeChains(ProtocolDecl, TUScope);
   }
-  // Create the built-in decls/typedefs for 'id' and 'Class'.
+  // Create the built-in typedef for 'id'.
   if (Context.getObjCIdType().isNull()) {
-    ObjCInterfaceDecl *IdIDecl =
-      ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
-                                &Context.Idents.get("id"), 
-                                SourceLocation(), true);
-    QualType IdIType = Context.getObjCInterfaceType(IdIDecl);
-    QualType ObjCIdType = Context.getObjCObjectPointerType(IdIType);
-
-    TypedefDecl *IdTypedef = TypedefDecl::Create(Context, CurContext,
-                                                 SourceLocation(),
-                                                 &Context.Idents.get("id"),
-                                                 ObjCIdType);
+    TypedefDecl *IdTypedef = 
+      TypedefDecl::Create( 
+        Context, CurContext, SourceLocation(), &Context.Idents.get("id"),
+        Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy)
+      );
     PushOnScopeChains(IdTypedef, TUScope);
     Context.setObjCIdType(Context.getTypeDeclType(IdTypedef));
   }
-  // Create the built-in decls/typedefs and type for "Class".
+  // Create the built-in typedef for 'Class'.
   if (Context.getObjCClassType().isNull()) {
-    ObjCInterfaceDecl *ClassIDecl =
-      ObjCInterfaceDecl::Create(Context, CurContext, SourceLocation(),
-                                &Context.Idents.get("Class"), 
-                                SourceLocation(), true);
-    QualType ClassIType = Context.getObjCInterfaceType(ClassIDecl);
-    QualType ObjCClassType = Context.getObjCObjectPointerType(ClassIType);
-    
-    TypedefDecl *ClassTypedef = TypedefDecl::Create(Context, CurContext,
-                                                    SourceLocation(),
-                                                    &Context.Idents.get("Class"),
-                                                    ObjCClassType);
+    TypedefDecl *ClassTypedef = 
+      TypedefDecl::Create( 
+        Context, CurContext, SourceLocation(), &Context.Idents.get("Class"),
+        Context.getObjCObjectPointerType(Context.ObjCBuiltinClassTy)
+      );
     PushOnScopeChains(ClassTypedef, TUScope);
     Context.setObjCClassType(Context.getTypeDeclType(ClassTypedef));
   }

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jul 15 13:40:39 2009
@@ -2338,9 +2338,11 @@
                        << IDecl->getDeclName() << &Member
                        << BaseExpr->getSourceRange());
   }
-  // Handle properties on qualified "id" protocols.
-  const ObjCObjectPointerType *QIdTy;
-  if (OpKind == tok::period && (QIdTy = BaseType->getAsObjCQualifiedIdType())) {
+  // Handle properties on 'id' and qualified "id".
+  if (OpKind == tok::period && (BaseType->isObjCIdType() || 
+                                BaseType->isObjCQualifiedIdType())) {
+    const ObjCObjectPointerType *QIdTy = BaseType->getAsObjCObjectPointerType();
+    
     // Check protocols on qualified interfaces.
     Selector Sel = PP.getSelectorTable().getNullarySelector(&Member);
     if (Decl *PMDecl = FindGetterNameDecl(QIdTy, Member, Sel, Context)) {
@@ -3531,6 +3533,8 @@
       return CheckPointeeTypesForAssignment(lhptee, rhptee);
     }
     if (rhsType->isObjCObjectPointerType()) {
+      if (lhsType->isObjCBuiltinType() || rhsType->isObjCBuiltinType())
+        return Compatible;
       QualType lhptee = lhsType->getAsObjCObjectPointerType()->getPointeeType();
       QualType rhptee = rhsType->getAsObjCObjectPointerType()->getPointeeType();
       return CheckPointeeTypesForAssignment(lhptee, rhptee);
@@ -4279,11 +4283,6 @@
         Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)
           << lType << rType << lex->getSourceRange() << rex->getSourceRange();
       }
-      if (lType->isObjCQualifiedIdType() && rType->isObjCQualifiedIdType()) {
-        if (!ObjCQualifiedIdTypesAreCompatible(lType, rType, true))
-          Diag(Loc, diag::warn_incompatible_qualified_id_operands)
-            << lType << rType << lex->getSourceRange() << rex->getSourceRange();
-      }
       ImpCastExprToType(rex, lType);
       return ResultTy;
     }

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Jul 15 13:40:39 2009
@@ -1011,15 +1011,9 @@
     FromType->getAsObjCObjectPointerType();
 
   if (ToObjCPtr && FromObjCPtr) {
-    // Objective C++: We're able to convert between "id" and a pointer
-    // to any interface (in both directions).
-    if (ToObjCPtr->isObjCIdType() && FromObjCPtr->isObjCIdType()) {
-      ConvertedType = ToType;
-      return true;
-    }
-    // Objective C++: Allow conversions between the Objective-C "Class" and a
+    // Objective C++: We're able to convert between "id" or "Class" and a
     // pointer to any interface (in both directions).
-    if (ToObjCPtr->isObjCClassType() || FromObjCPtr->isObjCClassType()) {
+    if (ToObjCPtr->isObjCBuiltinType() && FromObjCPtr->isObjCBuiltinType()) {
       ConvertedType = ToType;
       return true;
     }
@@ -1169,8 +1163,7 @@
       // Objective-C++ conversions are always okay.
       // FIXME: We should have a different class of conversions for the
       // Objective-C++ implicit conversions.
-      if (FromPtrType->isObjCIdType() || ToPtrType->isObjCIdType() ||
-          FromPtrType->isObjCClassType() || ToPtrType->isObjCClassType())
+      if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
         return false;
 
   }

Modified: cfe/trunk/test/SemaObjC/comptypes-3.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/comptypes-3.m?rev=75808&r1=75807&r2=75808&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/comptypes-3.m (original)
+++ cfe/trunk/test/SemaObjC/comptypes-3.m Wed Jul 15 13:40:39 2009
@@ -42,8 +42,8 @@
   obj_ac = obj_b;  // expected-warning {{incompatible type assigning 'id<MyProtocolB>', expected 'id<MyProtocolAC>'}}
   obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id<MyProtocolAB>', expected 'id<MyProtocolAC>'}}
 
-  if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
-  if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
+  if (obj_a == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolA>' and 'id<MyProtocolB>')}}
+  if (obj_b == obj_a) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolB>' and 'id<MyProtocolA>')}}
 
   if (obj_a == obj_ab) foo (); /* Ok */
   if (obj_ab == obj_a) foo (); /* Ok */ 
@@ -54,11 +54,11 @@
   if (obj_b == obj_ab) foo (); /* Ok */ 
   if (obj_ab == obj_b) foo (); /* Ok */ 
 
-  if (obj_b == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolB>' and 'id<MyProtocolAC>')}} 
-  if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolB>')}} 
+  if (obj_b == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolB>' and 'id<MyProtocolAC>')}} 
+  if (obj_ac == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAC>' and 'id<MyProtocolB>')}} 
 
-  if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}} 
-  if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}} 
+  if (obj_ab == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAB>' and 'id<MyProtocolAC>')}} 
+  if (obj_ac == obj_ab) foo (); // expected-warning {{comparison of distinct pointer types ('id<MyProtocolAC>' and 'id<MyProtocolAB>')}} 
 
   return 0;
 }

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

==============================================================================
--- cfe/trunk/test/SemaObjC/conditional-expr-3.m (original)
+++ cfe/trunk/test/SemaObjC/conditional-expr-3.m Wed Jul 15 13:40:39 2009
@@ -51,15 +51,15 @@
 }
 
 void f8(int cond, id<P0,P1> x0, id<P0,P2> x1) {
-  barP0(cond ? x0 : x1);
+  barP0(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
 }
 
 void f9(int cond, id<P0,P1> x0, id<P0,P2> x1) {
-  barP1(cond ? x0 : x1);
+  barP1(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
 }
 
 void f10(int cond, id<P0,P1> x0, id<P0,P2> x1) {
-  barP2(cond ? x0 : x1); // expected-warning {{incompatible type passing 'id<P0,P1>', expected 'id<P2>'}}
+  barP2(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id<P0,P1>' and 'id<P0,P2>')}}
 }
 
 int f11(int cond, A* a, B* b) {





More information about the cfe-commits mailing list