summaryrefslogtreecommitdiff
path: root/lib/Sema/SemaExprObjC.cpp
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-11-20 00:32:12 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-11-20 00:32:12 +0000
commite100097e424fb1ead2957f7c083bafb960043888 (patch)
tree5416c951173c364222e6303ea1cc1df28f2101c1 /lib/Sema/SemaExprObjC.cpp
parentff453c293db06a887e9d82ac44ad284931cd4519 (diff)
downloadclang-e100097e424fb1ead2957f7c083bafb960043888.tar.gz
clang-e100097e424fb1ead2957f7c083bafb960043888.tar.bz2
clang-e100097e424fb1ead2957f7c083bafb960043888.tar.xz
ObjectiveC ARC. validate toll free bridge casting
to or from 'id' and qualified-id types. // rdar://15454846 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@195178 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r--lib/Sema/SemaExprObjC.cpp28
1 files changed, 23 insertions, 5 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index cc8eacee61..6a0c09a4db 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -3196,14 +3196,24 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
castType->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass)))
+ if ((CastClass == ExprClass) ||
+ (CastClass && ExprClass->isSuperClassOf(CastClass)))
return true;
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< T << Target->getName() << castType->getPointeeType();
return true;
- } else {
+ } else if (castType->isObjCIdType() ||
+ (S.Context.ObjCObjectAdoptsQTypeProtocols(
+ castType, ExprClass)))
+ // ok to cast to 'id'.
+ // casting to id<p-list> is ok if bridge type adopts all of
+ // p-list protocols.
+ return true;
+ else {
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< T << Target->getName() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
}
@@ -3221,7 +3231,6 @@ static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
return false;
}
-// (CFErrorRef)ns
static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
QualType T = castType;
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
@@ -3240,16 +3249,25 @@ static bool CheckObjCBridgeCFCast(Sema &S, QualType castType, Expr *castExpr) {
castExpr->getType()->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *ExprClass
= InterfacePointerType->getObjectType()->getInterface();
- if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+ if ((CastClass == ExprClass) ||
+ (ExprClass && CastClass->isSuperClassOf(ExprClass)))
return true;
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
<< castExpr->getType()->getPointeeType() << T;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
return true;
- } else {
+ } else if (castExpr->getType()->isObjCIdType() ||
+ (S.Context.QIdProtocolsAdoptObjCObjectProtocols(
+ castExpr->getType(), CastClass)))
+ // ok to cast an 'id' expression to a CFtype.
+ // ok to cast an 'id<plist>' expression to CFtype provided plist
+ // adopts all of CFtype's ObjetiveC's class plist.
+ return true;
+ else {
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
<< castExpr->getType() << castType;
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
return true;
}
}