diff options
Diffstat (limited to 'clang/lib/Sema/SemaExprObjC.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 2db2c77c4bc..6ff6bef1ec7 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -3165,6 +3165,38 @@ diagnoseObjCARCConversion(Sema &S, SourceRange castRange, << 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 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, 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. |

