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
/// 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
///
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();
}
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);
}
unsigned NewWidth, bool NewSign,
SourceLocation Loc, unsigned DiagID);
+ bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS,
+ bool ForCompare);
+
+
void InitBuiltinVaListType();
//===--------------------------------------------------------------------===//
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;
}
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);
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);
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);
return Context.IntTy;
}
if ((lType->isObjCQualifiedIdType() || rType->isObjCQualifiedIdType())
- && Context.ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
+ && ObjCQualifiedIdTypesAreCompatible(lType, rType, true)) {
ImpCastExprToType(rex, lType);
return Context.IntTy;
}
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;
+}
+