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)