ObjetiveC ARC. Start diagnosing invalid toll free bridging.

// rdar://15454846.

llvm-svn: 194915
This commit is contained in:
Fariborz Jahanian 2013-11-16 01:45:25 +00:00
parent b37c431d53
commit f07183ce94
4 changed files with 27 additions and 12 deletions

View File

@ -381,6 +381,8 @@ def AutomaticReferenceCounting : DiagGroup<"arc",
def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
[ARCRepeatedUseOfWeakMaybe]>;
def ObjCBridge : DiagGroup<"arc-bridge-cast">;
def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
def Protocol : DiagGroup<"protocol">;

View File

@ -2449,6 +2449,8 @@ def err_objc_bridge_not_pointert_to_struct : Error<
"'objc_bridge' attribute must be applied to a pointer to struct type">;
def err_objc_bridged_not_interface : Error<
"CF object of type %0 is bridged to '%1', which is not an Objective-C class">;
def warn_objc_invalid_bridge : Warning<
"%0 bridges to %1, not %2">, InGroup<ObjCBridge>;
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;

View File

@ -3172,23 +3172,32 @@ static bool CheckObjCBridgeCast(Sema &S, QualType castType, Expr *castExpr) {
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)) {
NamedDecl *Target = R.getFoundDecl();
if (Target && !isa<ObjCInterfaceDecl>(Target)) {
S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
<< castExpr->getType() << Parm->getName();
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
S.Diag(Target->getLocStart(), diag::note_declared_at);
Target = R.getFoundDecl();
if (Target && isa<ObjCInterfaceDecl>(Target)) {
ObjCInterfaceDecl *ExprClass = cast<ObjCInterfaceDecl>(Target);
if (const ObjCObjectPointerType *InterfacePointerType =
castType->getAsObjCInterfacePointerType()) {
ObjCInterfaceDecl *CastClass
= InterfacePointerType->getObjectType()->getInterface();
if ((CastClass == ExprClass) || (CastClass && ExprClass->isSuperClassOf(CastClass)))
return true;
S.Diag(castExpr->getLocStart(), diag::warn_objc_invalid_bridge)
<< TDNDecl->getName() << Target->getName() << CastClass->getName();
return true;
}
}
} else {
S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
<< castExpr->getType() << Parm->getName();
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
}
S.Diag(castExpr->getLocStart(), diag::err_objc_bridged_not_interface)
<< castExpr->getType() << Parm->getName();
S.Diag(TDNDecl->getLocStart(), diag::note_declared_at);
if (Target)
S.Diag(Target->getLocStart(), diag::note_declared_at);
}
return true;
}

View File

@ -48,6 +48,8 @@ typedef CFErrorRef1 CFErrorRef2;
@class NSString;
id Test2(CFErrorRef2 cf) {
return (NSString *)cf;
void Test2(CFErrorRef2 cf) {
(void)(NSString *)cf; // expected-warning {{CFErrorRef bridges to NSError, not NSString}}
(void)(NSError *)cf; // okay
(void)(MyError*)cf; // okay,
}