ObjectiveC ARC. Adopt objc_bridge attribute
on struct/union/class instead of typedef of
such types. // rdar://15454846
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@195061 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 3cdb727..6a5d608 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -10072,6 +10072,31 @@
}
}
+static inline bool isTollFreeBridgeCFRefType(TypedefDecl *TD) {
+ TypedefNameDecl * TDefNameDecl = TD;
+ const Type *TP = TDefNameDecl->getUnderlyingType().getTypePtr();
+ while (const TypedefType *TDef = dyn_cast<TypedefType>(TP)) {
+ TDefNameDecl = TDef->getDecl();
+ TP = TDefNameDecl->getUnderlyingType().getTypePtr();
+ }
+
+ StringRef TDName = TDefNameDecl->getIdentifier()->getName();
+ return (TDName.startswith("CF") && TDName.endswith("Ref"));
+}
+
+/// CheckObjCBridgeAttribute - Checks that objc_bridge attribute is
+/// properly applied to a typedef of a pointer to struct/union/class
+static void CheckObjCBridgeAttribute(Sema &S, TypedefDecl *TD) {
+ QualType T = TD->getUnderlyingType();
+ if (!T->isPointerType())
+ return;
+ T = T->getPointeeType();
+ if (T->isStructureType() || T->isUnionType() || T->isClassType())
+ if (RecordDecl *RD = T->getAs<RecordType>()->getDecl())
+ if (RD->hasAttr<ObjCBridgeAttr>() && !isTollFreeBridgeCFRefType(TD))
+ S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_cftype);
+}
+
TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
TypeSourceInfo *TInfo) {
assert(D.getIdentifier() && "Wrong callback for declspec without declarator");
@@ -10095,6 +10120,8 @@
return NewTD;
}
+ CheckObjCBridgeAttribute(*this, NewTD);
+
if (D.getDeclSpec().isModulePrivateSpecified()) {
if (CurContext->isFunctionOrMethod())
Diag(NewTD->getLocation(), diag::err_module_private_local)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 7987a18..77f7905 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -207,11 +207,6 @@
return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
}
-static inline bool isTollFreeBridgeCFRefType(TypedefNameDecl *TD, ASTContext &Ctx) {
- StringRef TDName = TD->getIdentifier()->getName();
- return (TDName.startswith("CF") && TDName.endswith("Ref"));
-}
-
static unsigned getNumAttributeArgs(const AttributeList &Attr) {
// FIXME: Include the type in the argument list.
return Attr.getNumArgs() + Attr.hasParsedType();
@@ -4396,34 +4391,7 @@
static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,
const AttributeList &Attr) {
- if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
- QualType T = TD->getUnderlyingType();
- if (T->isPointerType()) {
- T = T->getPointeeType();
- if (T->isRecordType()) {
- RecordDecl *RD = T->getAs<RecordType>()->getDecl();
- if (!RD || RD->isUnion()) {
- S.Diag(D->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)
- << Attr.getRange();
- return;
- }
- } else {
- S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)
- << Attr.getRange();
- return;
- }
- } else {
- S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)
- << Attr.getRange();
- return;
- }
- // Check for T being a CFType goes here.
- if (!isTollFreeBridgeCFRefType(TD, S.Context)) {
- S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_cftype);
- return;
- }
- }
- else {
+ if (!isa<RecordDecl>(D)) {
S.Diag(D->getLocStart(), diag::err_objc_bridge_attribute);
return;
}
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index b59e0a6..69d7b9e 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -3165,15 +3165,26 @@
<< castRange << castExpr->getSourceRange();
}
+static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) {
+ TypedefNameDecl *TDNDecl = TD->getDecl();
+ QualType QT = TDNDecl->getUnderlyingType();
+ if (QT->isPointerType()) {
+ QT = QT->getPointeeType();
+ if (QT->isStructureType() || QT->isUnionType() || QT->isClassType())
+ if (RecordDecl *RD = QT->getAs<RecordType>()->getDecl())
+ if (RD->hasAttr<ObjCBridgeAttr>())
+ return RD->getAttr<ObjCBridgeAttr>();
+ }
+ return 0;
+}
+
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();
- if (TDNDecl->hasAttr<ObjCBridgeAttr>()) {
- ObjCBridgeAttr *ObjCBAttr = TDNDecl->getAttr<ObjCBridgeAttr>();
- IdentifierInfo *Parm = ObjCBAttr->getBridgedType();
- NamedDecl *Target = 0;
- if (Parm && S.getLangOpts().ObjC1) {
+ if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
+ NamedDecl *Target = 0;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);
@@ -3215,11 +3226,9 @@
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) {
+ if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {
+ if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {
+ NamedDecl *Target = 0;
// Check for an existing type with this name.
LookupResult R(S, DeclarationName(Parm), SourceLocation(),
Sema::LookupOrdinaryName);