diff options
author | Steve Naroff <snaroff@apple.com> | 2009-07-15 18:40:39 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-07-15 18:40:39 +0000 |
commit | de2e22d33afec98324a66a358dfe0951b3c7259a (patch) | |
tree | d4bb699e42464c745d95b1d753e62a916d3415ed /lib | |
parent | 92db2841691b2f2a99294872ead8887854297ed7 (diff) |
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
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 64 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 36 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 13 |
9 files changed, 74 insertions, 84 deletions
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<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())) 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 "<overloaded function type>"; case Dependent: return "<dependent type>"; 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<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); 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; } |