summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-11-16 19:16:32 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-11-16 19:16:32 +0000
commit8a0210e535c5dc712f03bb323242e4d9bfa89fd8 (patch)
treec82b1baac3314ff9026d9837318e035ece5f0c9a /clang/lib
parentc6f955763ebc7d7830845ce2393493bf5357b8c1 (diff)
downloadbcm5719-llvm-8a0210e535c5dc712f03bb323242e4d9bfa89fd8.tar.gz
bcm5719-llvm-8a0210e535c5dc712f03bb323242e4d9bfa89fd8.zip
ObjectiveC ARC. Validate toll free bridge casting
of ObjectiveC objects to CF types when CF type has the objc_bridge attribute. llvm-svn: 194930
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Sema/SemaExprObjC.cpp54
1 files changed, 51 insertions, 3 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp
index f226af3ae0a..ea1f2a98e3d 100644
--- a/clang/lib/Sema/SemaExprObjC.cpp
+++ b/clang/lib/Sema/SemaExprObjC.cpp
@@ -3165,7 +3165,7 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange,
<< castRange << castExpr->getSourceRange();
}
-static bool CheckObjCBridgeCast(Sema &S, QualType castType, Expr *castExpr) {
+static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {
QualType T = castExpr->getType();
while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {
TypedefNameDecl *TDNDecl = TD->getDecl();
@@ -3193,7 +3193,7 @@ static bool CheckObjCBridgeCast(Sema &S, QualType castType, Expr *castExpr) {
}
}
}
- S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
+ S.Diag(castExpr->getLocStart(), diag::err_objc_cf_bridged_not_interface)
<< castExpr->getType() << Parm->getName();
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
if (Target)
@@ -3206,6 +3206,49 @@ static bool CheckObjCBridgeCast(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())) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ if (TDNDecl->hasAttr<ObjCBridgeAttr>()) {
+ ObjCBridgeAttr *ObjCBAttr = TDNDecl->getAttr<ObjCBridgeAttr>();
+ IdentifierInfo *Parm = ObjCBAttr->getBridgedType();
+ NamedDecl *Target = 0;
+ if (Parm && S.getLangOpts().ObjC1) {
+ // Check for an existing type with this name.
+ LookupResult R(S, DeclarationName(Parm), SourceLocation(),
+ Sema::LookupOrdinaryName);
+ if (S.LookupName(R, S.TUScope)) {
+ Target = R.getFoundDecl();
+ if (Target && isa<ObjCInterfaceDecl>(Target)) {
+ ObjCInterfaceDecl *CastClass = cast<ObjCInterfaceDecl>(Target);
+ if (const ObjCObjectPointerType *InterfacePointerType =
+ castExpr->getType()->getAsObjCInterfacePointerType()) {
+ ObjCInterfaceDecl *ExprClass
+ = InterfacePointerType->getObjectType()->getInterface();
+ if ((CastClass == ExprClass) || (ExprClass && CastClass->isSuperClassOf(ExprClass)))
+ return true;
+ S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge_to_cf)
+ << ExprClass->getName() << TDNDecl->getName();
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ return true;
+ }
+ }
+ }
+ S.Diag(castExpr->getLocStart(), diag::err_objc_ns_bridged_invalid_cfobject)
+ << castExpr->getType() << castType;
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ if (Target)
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ return true;
+ }
+ T = TDNDecl->getUnderlyingType();
+ }
+ return false;
+}
+
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&castExpr, CheckedConversionKind CCK,
@@ -3266,7 +3309,12 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
(CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
- if (CheckObjCBridgeCast(*this, castType, castExpr))
+ if (CheckObjCBridgeNSCast(*this, castType, castExpr))
+ return ACR_okay;
+
+ if (castACTC == ACTC_coreFoundation && exprACTC == ACTC_retainable &&
+ (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
+ if (CheckObjCBridgeCFCast(*this, castType, castExpr))
return ACR_okay;
OpenPOWER on IntegriCloud