diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 1 | ||||
-rw-r--r-- | include/clang/AST/DeclObjC.h | 6 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 176 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 167 |
7 files changed, 200 insertions, 222 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 188d440407..bec9efa2b1 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -335,7 +335,6 @@ public: bool builtinTypesAreCompatible(QualType, QualType); bool vectorTypesAreCompatible(QualType, QualType); - bool ObjCQualifiedIdTypesAreCompatible(QualType, QualType, bool = false); bool objcTypesAreCompatible(QualType, QualType); bool isObjCIdType(QualType T) const { if (!IdStructType) // ObjC isn't enabled diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 04bf38b87d..a1e0f256fc 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -420,11 +420,15 @@ private: /// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ /// feature with nice semantics and lousy syntax:-). Here is an example: /// -/// @protocol NSDraggingInfo +/// @protocol NSDraggingInfo <refproto1, refproto2> /// - (NSWindow *)draggingDestinationWindow; /// - (NSImage *)draggedImage; /// @end /// +/// This says that NSDraggingInfo requires two methods and requires everything +/// that the two "referenced protocols" 'refproto1' and 'refproto2' require as +/// well. +/// /// @interface ImplementsNSDraggingInfo : NSObject <NSDraggingInfo> /// @end /// diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 65c4e0567f..439a99c4b2 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1507,182 +1507,6 @@ areCompatObjCQualInterfaces(const ObjCQualifiedInterfaceType *LHS, return false; } -/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the -/// inheritance hierarchy of 'rProto'. -static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, - ObjCProtocolDecl *rProto) { - if (lProto == rProto) - return true; - ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); - for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) - if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) - return true; - return false; -} - -/// ClassImplementsProtocol - Checks that 'lProto' protocol -/// has been implemented in IDecl class, its super class or categories (if -/// lookupCategory is true). -static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, - ObjCInterfaceDecl *IDecl, - bool lookupCategory) { - - // 1st, look up the class. - ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); - for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { - if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) - return true; - } - - // 2nd, look up the category. - if (lookupCategory) - for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) { - protoList = CDecl->getReferencedProtocols(); - for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { - if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) - return true; - } - } - - // 3rd, look up the super class(s) - if (IDecl->getSuperClass()) - return - ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory); - - return false; -} - -/// ObjCQualifiedIdTypesAreCompatible - Compares two types, at least -/// one of which is a protocol qualified 'id' type. When 'compare' -/// is true it is for comparison; when false, for assignment/initialization. -bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, - QualType rhs, - bool compare) { - // match id<P..> with an 'id' type in all cases. - if (const PointerType *PT = lhs->getAsPointerType()) { - QualType PointeeTy = PT->getPointeeType(); - if (isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) - return true; - } else if (const PointerType *PT = rhs->getAsPointerType()) { - QualType PointeeTy = PT->getPointeeType(); - if (isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) - return true; - } - - ObjCQualifiedInterfaceType *lhsQI = 0; - ObjCQualifiedInterfaceType *rhsQI = 0; - ObjCInterfaceDecl *lhsID = 0; - ObjCInterfaceDecl *rhsID = 0; - ObjCQualifiedIdType *lhsQID = dyn_cast<ObjCQualifiedIdType>(lhs); - ObjCQualifiedIdType *rhsQID = dyn_cast<ObjCQualifiedIdType>(rhs); - - if (lhsQID) { - if (!rhsQID && rhs->getTypeClass() == Type::Pointer) { - QualType rtype = - cast<PointerType>(rhs.getCanonicalType())->getPointeeType(); - rhsQI = - dyn_cast<ObjCQualifiedInterfaceType>( - rtype.getCanonicalType().getTypePtr()); - if (!rhsQI) { - ObjCInterfaceType *IT = dyn_cast<ObjCInterfaceType>( - rtype.getCanonicalType().getTypePtr()); - if (IT) - rhsID = IT->getDecl(); - } - } - if (!rhsQI && !rhsQID && !rhsID) - return false; - - ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; - if (rhsQI) { - RHSProtoI = rhsQI->qual_begin(); - RHSProtoE = rhsQI->qual_end(); - } else if (rhsQID) { - RHSProtoI = rhsQID->qual_begin(); - RHSProtoE = rhsQID->qual_end(); - } - - for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { - ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); - bool match = 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. - if (rhsID) { - if (ClassImplementsProtocol(lhsProto, rhsID, true)) - match = true; - } else { - for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { - ObjCProtocolDecl *rhsProto = *RHSProtoI; - if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || - compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { - match = true; - break; - } - } - } - if (!match) - return false; - } - } - else if (rhsQID) { - if (!lhsQID && lhs->getTypeClass() == Type::Pointer) { - QualType ltype = - cast<PointerType>(lhs.getCanonicalType())->getPointeeType(); - lhsQI = - dyn_cast<ObjCQualifiedInterfaceType>( - ltype.getCanonicalType().getTypePtr()); - if (!lhsQI) { - ObjCInterfaceType *IT = dyn_cast<ObjCInterfaceType>( - ltype.getCanonicalType().getTypePtr()); - if (IT) - lhsID = IT->getDecl(); - } - } - if (!lhsQI && !lhsQID && !lhsID) - return false; - - ObjCQualifiedIdType::qual_iterator LHSProtoI, LHSProtoE; - if (lhsQI) { - LHSProtoI = lhsQI->qual_begin(); - LHSProtoE = lhsQI->qual_end(); - } else if (lhsQID) { - LHSProtoI = lhsQID->qual_begin(); - LHSProtoE = lhsQID->qual_end(); - } - - bool match = false; - // for static type vs. qualified 'id' type, check that class implements - // one of 'id's protocols. - if (lhsID) { - for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { - ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); - if (ClassImplementsProtocol(rhsProto, lhsID, compare)) { - match = true; - break; - } - } - } else { - for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { - match = false; - ObjCProtocolDecl *lhsProto = *LHSProtoI; - for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { - ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); - if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || - compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { - match = true; - break; - } - } - } - } - if (!match) - return false; - } - return true; -} bool ASTContext::vectorTypesAreCompatible(QualType lhs, QualType rhs) { const VectorType *lVector = lhs->getAsVectorType(); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 16f54cae13..f80f3641da 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -429,42 +429,22 @@ const OCUVectorType *Type::getAsOCUVectorType() const { } const ObjCInterfaceType *Type::getAsObjCInterfaceType() const { - // Are we directly an ObjCInterface type? - if (const ObjCInterfaceType *VTy = dyn_cast<ObjCInterfaceType>(this)) - return VTy; - - // If the canonical form of this type isn't the right kind, reject it. - if (!isa<ObjCInterfaceType>(CanonicalType)) { - // Look through type qualifiers - if (isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType())) - return CanonicalType.getUnqualifiedType()->getAsObjCInterfaceType(); - return 0; - } - - // If this is a typedef for an objc interface type, strip the typedef off - // without losing all typedef information. - return getDesugaredType()->getAsObjCInterfaceType(); + // There is no sugar for ObjCInterfaceType's, just return the canonical + // type pointer if it is the right class. + return dyn_cast<ObjCInterfaceType>(CanonicalType); } const ObjCQualifiedInterfaceType * Type::getAsObjCQualifiedInterfaceType() const { - // Are we directly an ObjCQualifiedInterfaceType? - if (const ObjCQualifiedInterfaceType *VTy = - dyn_cast<ObjCQualifiedInterfaceType>(this)) - return VTy; - - // If the canonical form of this type isn't the right kind, reject it. - if (!isa<ObjCQualifiedInterfaceType>(CanonicalType)) { - // Look through type qualifiers - if (isa<ObjCQualifiedInterfaceType>(CanonicalType.getUnqualifiedType())) - return CanonicalType.getUnqualifiedType()-> - getAsObjCQualifiedInterfaceType(); - return 0; - } - - // If this is a typedef for an objc qual interface type, strip the typedef off - // without losing all typedef information. - return getDesugaredType()->getAsObjCQualifiedInterfaceType(); + // There is no sugar for ObjCQualifiedInterfaceType's, just return the canonical + // type pointer if it is the right class. + return dyn_cast<ObjCQualifiedInterfaceType>(CanonicalType); +} + +const ObjCQualifiedIdType *Type::getAsObjCQualifiedIdType() const { + // There is no sugar for ObjCQualifiedIdType's, just return the canonical + // type pointer if it is the right class. + return dyn_cast<ObjCQualifiedIdType>(CanonicalType); } diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 98ecf87ce6..70aaf24791 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -825,6 +825,10 @@ private: unsigned NewWidth, bool NewSign, SourceLocation Loc, unsigned DiagID); + bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, + bool ForCompare); + + void InitBuiltinVaListType(); //===--------------------------------------------------------------------===// diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a661d0172b..a528519d26 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1185,9 +1185,8 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return Incompatible; } - if (lhsType->isObjCQualifiedIdType() - || rhsType->isObjCQualifiedIdType()) { - if (Context.ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType)) + if (lhsType->isObjCQualifiedIdType() || rhsType->isObjCQualifiedIdType()) { + if (ObjCQualifiedIdTypesAreCompatible(lhsType, rhsType, false)) return Compatible; return Incompatible; } @@ -1368,9 +1367,9 @@ inline QualType Sema::CheckAdditionOperands( // C99 6.5.6 return InvalidOperands(loc, lex, rex); } -inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) -{ +// C99 6.5.6 +QualType Sema::CheckSubtractionOperands(Expr *&lex, Expr *&rex, + SourceLocation loc, bool isCompAssign) { if (lex->getType()->isVectorType() || rex->getType()->isVectorType()) return CheckVectorOperands(loc, lex, rex); @@ -1437,8 +1436,9 @@ inline QualType Sema::CheckSubtractionOperands( // C99 6.5.6 return InvalidOperands(loc, lex, rex); } -inline QualType Sema::CheckShiftOperands( // C99 6.5.7 - Expr *&lex, Expr *&rex, SourceLocation loc, bool isCompAssign) { +// C99 6.5.7 +QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation loc, + bool isCompAssign) { // C99 6.5.7p2: Each of the operands shall have integer type. if (!lex->getType()->isIntegerType() || !rex->getType()->isIntegerType()) return InvalidOperands(loc, lex, rex); @@ -1453,9 +1453,9 @@ inline QualType Sema::CheckShiftOperands( // C99 6.5.7 return lex->getType(); } -inline QualType Sema::CheckCompareOperands( // C99 6.5.8 - Expr *&lex, Expr *&rex, SourceLocation loc, bool isRelational) -{ +// C99 6.5.8 +QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation loc, + bool isRelational) { // C99 6.5.8p3 / C99 6.5.9p4 if (lex->getType()->isArithmeticType() && rex->getType()->isArithmeticType()) UsualArithmeticConversions(lex, rex); @@ -1514,7 +1514,7 @@ inline QualType Sema::CheckCompareOperands( // C99 6.5.8 return Context.IntTy; } if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType()) - && Context.ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) { + && ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) { ImpCastExprToType(rex, lType); return Context.IntTy; } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index ec6e41bf39..63dd0d780f 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -297,3 +297,170 @@ Sema::ExprResult Sema::ActOnInstanceMessage( return new ObjCMessageExpr(RExpr, Sel, returnType, Method, lbrac, rbrac, ArgExprs, NumArgs); } + +//===----------------------------------------------------------------------===// +// ObjCQualifiedIdTypesAreCompatible - Compatibility testing for qualified id's. +//===----------------------------------------------------------------------===// + +/// ProtocolCompatibleWithProtocol - return 'true' if 'lProto' is in the +/// inheritance hierarchy of 'rProto'. +static bool ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, + ObjCProtocolDecl *rProto) { + if (lProto == rProto) + return true; + ObjCProtocolDecl** RefPDecl = rProto->getReferencedProtocols(); + for (unsigned i = 0; i < rProto->getNumReferencedProtocols(); i++) + if (ProtocolCompatibleWithProtocol(lProto, RefPDecl[i])) + return true; + return false; +} + +/// ClassImplementsProtocol - Checks that 'lProto' protocol +/// has been implemented in IDecl class, its super class or categories (if +/// lookupCategory is true). +static bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, + ObjCInterfaceDecl *IDecl, + bool lookupCategory) { + + // 1st, look up the class. + ObjCProtocolDecl **protoList = IDecl->getReferencedProtocols(); + for (unsigned i = 0; i < IDecl->getNumIntfRefProtocols(); i++) { + if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) + return true; + } + + // 2nd, look up the category. + if (lookupCategory) + for (ObjCCategoryDecl *CDecl = IDecl->getCategoryList(); CDecl; + CDecl = CDecl->getNextClassCategory()) { + protoList = CDecl->getReferencedProtocols(); + for (unsigned i = 0; i < CDecl->getNumReferencedProtocols(); i++) { + if (ProtocolCompatibleWithProtocol(lProto, protoList[i])) + return true; + } + } + + // 3rd, look up the super class(s) + if (IDecl->getSuperClass()) + return + ClassImplementsProtocol(lProto, IDecl->getSuperClass(), lookupCategory); + + return false; +} + +bool Sema::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, + bool compare) { + // Allow id<P..> and an 'id' or void* type in all cases. + if (const PointerType *PT = lhs->getAsPointerType()) { + QualType PointeeTy = PT->getPointeeType(); + if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) + return true; + } else if (const PointerType *PT = rhs->getAsPointerType()) { + QualType PointeeTy = PT->getPointeeType(); + if (Context.isObjCIdType(PointeeTy) || PointeeTy->isVoidType()) + return true; + } + + const ObjCQualifiedInterfaceType *lhsQI = 0; + const ObjCQualifiedInterfaceType *rhsQI = 0; + ObjCInterfaceDecl *lhsID = 0; + ObjCInterfaceDecl *rhsID = 0; + const ObjCQualifiedIdType *lhsQID = lhs->getAsObjCQualifiedIdType(); + const ObjCQualifiedIdType *rhsQID = rhs->getAsObjCQualifiedIdType(); + + if (lhsQID) { + if (!rhsQID && rhs->isPointerType()) { + QualType rtype = rhs->getAsPointerType()->getPointeeType(); + rhsQI = rtype->getAsObjCQualifiedInterfaceType(); + if (!rhsQI) { + if (const ObjCInterfaceType *IT = rtype->getAsObjCInterfaceType()) + rhsID = IT->getDecl(); + } + } + if (!rhsQI && !rhsQID && !rhsID) + return false; + + ObjCQualifiedIdType::qual_iterator RHSProtoI, RHSProtoE; + if (rhsQI) { + RHSProtoI = rhsQI->qual_begin(); + RHSProtoE = rhsQI->qual_end(); + } else if (rhsQID) { + RHSProtoI = rhsQID->qual_begin(); + RHSProtoE = rhsQID->qual_end(); + } + + for (unsigned i =0; i < lhsQID->getNumProtocols(); i++) { + ObjCProtocolDecl *lhsProto = lhsQID->getProtocols(i); + bool match = 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. + if (rhsID) { + if (ClassImplementsProtocol(lhsProto, rhsID, true)) + match = true; + } else { + for (; RHSProtoI != RHSProtoE; ++RHSProtoI) { + ObjCProtocolDecl *rhsProto = *RHSProtoI; + if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || + compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { + match = true; + break; + } + } + } + if (!match) + return false; + } + } else if (rhsQID) { + if (!lhsQID && lhs->isPointerType()) { + QualType ltype = lhs->getAsPointerType()->getPointeeType(); + lhsQI = ltype->getAsObjCQualifiedInterfaceType(); + if (!lhsQI) { + if (const ObjCInterfaceType *IT = ltype->getAsObjCInterfaceType()) + lhsID = IT->getDecl(); + } + } + if (!lhsQI && !lhsQID && !lhsID) + return false; + + ObjCQualifiedIdType::qual_iterator LHSProtoI, LHSProtoE; + if (lhsQI) { + LHSProtoI = lhsQI->qual_begin(); + LHSProtoE = lhsQI->qual_end(); + } else if (lhsQID) { + LHSProtoI = lhsQID->qual_begin(); + LHSProtoE = lhsQID->qual_end(); + } + + bool match = false; + // for static type vs. qualified 'id' type, check that class implements + // one of 'id's protocols. + if (lhsID) { + for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { + ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); + if (ClassImplementsProtocol(rhsProto, lhsID, compare)) { + match = true; + break; + } + } + } else { + for (; LHSProtoI != LHSProtoE; ++LHSProtoI) { + match = false; + ObjCProtocolDecl *lhsProto = *LHSProtoI; + for (unsigned j = 0; j < rhsQID->getNumProtocols(); j++) { + ObjCProtocolDecl *rhsProto = rhsQID->getProtocols(j); + if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || + compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto)) { + match = true; + break; + } + } + } + } + if (!match) + return false; + } + return true; +} + |