From: Steve Naroff Date: Wed, 15 Jul 2009 18:40:39 +0000 (+0000) Subject: Implement the ObjC pseudo built-in types as clang "BuiltinType's". I say pseudo built... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de2e22d33afec98324a66a358dfe0951b3c7259a;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75808 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 56b3e69833..f52d828f67 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -106,7 +106,7 @@ class ASTContext { 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 @@ class ASTContext { 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 @@ public: 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 @@ public: /// 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 @@ public: /// 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 @@ public: 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"); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 7ddf90bcab..9843bbb012 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -404,6 +404,7 @@ public: bool isObjCQualifiedIdType() const; // id 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 @@ public: 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 @@ public: /// 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 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode { 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(T.getTypePtr()); - } - static void setClassInterface(QualType T) { - ClassInterfaceT = dyn_cast(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 @@ public: 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

". - 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

". + bool isObjCQualifiedIdType() const { + return getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCId) && + Protocols.size(); + } + /// isObjCQualifiedClassType - true for "Class

". + 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 @@ inline bool Type::isObjCQualifiedInterfaceType() const { return isa(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(CanonicalType.getUnqualifiedType()); } diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 6926633a40..f552a2faf0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1457,8 +1457,6 @@ def err_cannot_initialize_decl : Error< "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< diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index a1feec3a6a..3e3b95efff 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -333,7 +333,11 @@ namespace clang { /// \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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 13f35dc3a0..fb28188789 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -201,8 +201,13 @@ void ASTContext::InitBuiltinTypes() { 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 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT, 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 ASTContext::getObjCFastEnumerationStateType() QualType FieldTypes[] = { UnsignedLongTy, - getPointerType(ObjCIdType), + getPointerType(ObjCIdTypedefType), getPointerType(UnsignedLongTy), getConstantArrayType(UnsignedLongTy, llvm::APInt(32, 5), ArrayType::Normal, 0) @@ -3018,13 +3023,7 @@ void ASTContext::setBuiltinVaListType(QualType T) { } 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::setObjCProtoType(QualType QT) { } 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 @@ static bool areCompatVectorTypes(const VectorType *LHS, /// 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

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())) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 9edb9c046d..18fa76bf25 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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 @@ const char *BuiltinType::getName(const LangOptions &LO) const { case Overload: return ""; case Dependent: return ""; case UndeducedAuto: return "auto"; + case ObjCId: return "id"; + case ObjCClass: return "Class"; } } @@ -1687,14 +1686,6 @@ void TypenameType::getAsStringInternal(std::string &InnerString, const PrintingP 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 ObjCInterfaceType::getAsStringInternal(std::string &InnerString, const Prin 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 += '<'; diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index c617939e35..e97cbbd66c 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -228,6 +228,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { switch (cast(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); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index cd0e2eae7d..5340cd7262 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -577,6 +577,8 @@ void CXXNameMangler::mangleType(const BuiltinType *T) { case BuiltinType::UndeducedAuto: assert(0 && "Should not see undeduced auto here"); break; + case BuiltinType::ObjCId: Out << "2id"; break; + case BuiltinType::ObjCClass: Out << "5Class"; break; } } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 012c6fecfe..8c26607b7c 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -1986,6 +1986,8 @@ QualType PCHReader::GetType(pch::TypeID ID) { 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"); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 333bcc9893..6a17f39f43 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -2009,6 +2009,8 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) { 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; diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 9b58e47746..39662511f1 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -149,35 +149,23 @@ void Sema::ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) { 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)); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 66d2cdcb38..19d890851a 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2338,9 +2338,11 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, << 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { 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 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, 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; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index bee3936048..35c5567503 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1011,15 +1011,9 @@ bool Sema::isObjCPointerConversion(QualType FromType, QualType ToType, 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 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType) { // 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; } diff --git a/test/SemaObjC/comptypes-3.m b/test/SemaObjC/comptypes-3.m index 2d8f19d806..0506bce7ad 100644 --- a/test/SemaObjC/comptypes-3.m +++ b/test/SemaObjC/comptypes-3.m @@ -42,8 +42,8 @@ int main() obj_ac = obj_b; // expected-warning {{incompatible type assigning 'id', expected 'id'}} obj_ac = obj_ab; // expected-warning {{incompatible type assigning 'id', expected 'id'}} - if (obj_a == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} - if (obj_b == obj_a) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_a == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} + if (obj_b == obj_a) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} if (obj_a == obj_ab) foo (); /* Ok */ if (obj_ab == obj_a) foo (); /* Ok */ @@ -54,11 +54,11 @@ int main() 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' and 'id')}} - if (obj_ac == obj_b) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_b == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} + if (obj_ac == obj_b) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} - if (obj_ab == obj_ac) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} - if (obj_ac == obj_ab) foo (); // expected-warning {{invalid operands to binary expression ('id' and 'id')}} + if (obj_ab == obj_ac) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} + if (obj_ac == obj_ab) foo (); // expected-warning {{comparison of distinct pointer types ('id' and 'id')}} return 0; } diff --git a/test/SemaObjC/conditional-expr-3.m b/test/SemaObjC/conditional-expr-3.m index 0b392d4882..9f1ee68c6f 100644 --- a/test/SemaObjC/conditional-expr-3.m +++ b/test/SemaObjC/conditional-expr-3.m @@ -51,15 +51,15 @@ void f7(int cond, id x, A *a) { } void f8(int cond, id x0, id x1) { - barP0(cond ? x0 : x1); + barP0(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id' and 'id')}} } void f9(int cond, id x0, id x1) { - barP1(cond ? x0 : x1); + barP1(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id' and 'id')}} } void f10(int cond, id x0, id x1) { - barP2(cond ? x0 : x1); // expected-warning {{incompatible type passing 'id', expected 'id'}} + barP2(cond ? x0 : x1); // expected-warning {{incompatible operand types ('id' and 'id')}} } int f11(int cond, A* a, B* b) {