ObjectiveC ARC. Lookup type associated with objc_bridage at
the point of CF object type-cast and issue diagnostic
if it is not a valid ObjectiveC class. // rdar//15454846.
This is wip.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@194861 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 2db2c77..6ff6bef 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -3165,6 +3165,38 @@
<< castRange << castExpr->getSourceRange();
}
+static bool CheckObjCBridgeCast(Sema &S, QualType castType, Expr *castExpr) {
+ QualType T = castExpr->getType();
+ 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();
+ 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)) {
+ NamedDecl *Target = R.getFoundDecl();
+ if (Target && !isa<ObjCInterfaceDecl>(Target)) {
+ S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
+ << castExpr->getType();
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ S.Diag(Target->getLocStart(), diag::note_declared_at);
+ }
+ } else {
+ S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
+ << castExpr->getType();
+ S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
+ }
+ }
+ return true;
+ }
+ T = TDNDecl->getUnderlyingType();
+ }
+ return false;
+}
+
Sema::ARCConversionResult
Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType,
Expr *&castExpr, CheckedConversionKind CCK,
@@ -3222,6 +3254,12 @@
if (castACTC == ACTC_indirectRetainable && exprACTC == ACTC_voidPtr &&
CCK != CCK_ImplicitConversion)
return ACR_okay;
+
+ if (castACTC == ACTC_retainable && exprACTC == ACTC_coreFoundation &&
+ (CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast))
+ if (CheckObjCBridgeCast(*this, castType, castExpr))
+ return ACR_okay;
+
switch (ARCCastChecker(Context, exprACTC, castACTC, false).Visit(castExpr)) {
// For invalid casts, fall through.