forked from OSchip/llvm-project
ObjectiveC ARC. Validate toll free bridge casting
of ObjectiveC objects to CF types when CF type has the objc_bridge attribute. llvm-svn: 194930
This commit is contained in:
parent
c6f955763e
commit
8a0210e535
|
@ -2447,10 +2447,14 @@ def err_objc_bridge_not_cftype : Error<
|
|||
"'objc_bridge' attribute must be applied to definition of CF types">;
|
||||
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<
|
||||
def err_objc_cf_bridged_not_interface : Error<
|
||||
"CF object of type %0 is bridged to '%1', which is not an Objective-C class">;
|
||||
def err_objc_ns_bridged_invalid_cfobject : Error<
|
||||
"ObjectiveC object of type %0 is bridged to %1, which is not valid CF object">;
|
||||
def warn_objc_invalid_bridge : Warning<
|
||||
"%0 bridges to %1, not %2">, InGroup<ObjCBridge>;
|
||||
def warn_objc_invalid_bridge_to_cf : Warning<
|
||||
"%0 cannot bridge to %1">, InGroup<ObjCBridge>;
|
||||
|
||||
// Function Parameter Semantic Analysis.
|
||||
def err_param_with_void_type : Error<"argument may not have 'void' type">;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
|
||||
// rdar://15454846
|
||||
|
||||
typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError))) CFErrorRef;
|
||||
typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError))) CFErrorRef; // expected-note {{declared here}}
|
||||
|
||||
typedef struct __CFMyColor * __attribute__((objc_bridge(12))) CFMyColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}
|
||||
|
||||
|
@ -48,8 +48,10 @@ typedef CFErrorRef1 CFErrorRef2;
|
|||
|
||||
@class NSString;
|
||||
|
||||
void Test2(CFErrorRef2 cf) {
|
||||
void Test2(CFErrorRef2 cf, NSError *ns, NSString *str) {
|
||||
(void)(NSString *)cf; // expected-warning {{CFErrorRef bridges to NSError, not NSString}}
|
||||
(void)(NSError *)cf; // okay
|
||||
(void)(MyError*)cf; // okay,
|
||||
(void)(CFErrorRef)ns; // okay
|
||||
(void)(CFErrorRef)str; // expected-warning {{NSString cannot bridge to CFErrorRef}}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue