<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Nov 18, 2013, at 5:24 PM, Aaron Ballman <<a href="mailto:aaron@aaronballman.com">aaron@aaronballman.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite">On Mon, Nov 18, 2013 at 7:09 PM, Fariborz Jahanian <<a href="mailto:fjahanian@apple.com">fjahanian@apple.com</a>> wrote:<br><blockquote type="cite">Author: fjahanian<br>Date: Mon Nov 18 18:09:48 2013<br>New Revision: 195061<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=195061&view=rev">http://llvm.org/viewvc/llvm-project?rev=195061&view=rev</a><br>Log:<br>ObjectiveC ARC. Adopt objc_bridge attribute<br>on struct/union/class instead of typedef of<br>such types. // <a href="rdar://15454846">rdar://15454846</a><br><br>Modified:<br>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>    cfe/trunk/lib/Sema/SemaDecl.cpp<br>    cfe/trunk/lib/Sema/SemaDeclAttr.cpp<br>    cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>    cfe/trunk/test/SemaObjC/objcbridge-attribute.m<br><br>Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=195061&r1=195060&r2=195061&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=195061&r1=195060&r2=195061&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 18 18:09:48 2013<br>@@ -2442,11 +2442,9 @@ def err_ns_bridged_not_interface : Error<br> def err_objc_bridge_not_id : Error<<br>   "parameter of 'objc_bridge' attribute must be a single name of an Objective-C class">;<br> def err_objc_bridge_attribute : Error<<br>-  "'objc_bridge' attribute must be put on a typedef only">;<br>+  "'objc_bridge' attribute must be applied to a struct, C++ class, or union">;<br></blockquote><br>Please use err_attribute_wrong_decl_type instead of a custom error message.<br></blockquote><div><br></div>In r<font face="Menlo"><span style="font-size: 11px;">195135. Also, per Doug’s comment earlier, I removed the two routines you had</span></font></div><div><font face="Menlo"><span style="font-size: 11px;">comments on.</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"><br></span></font></div><div><font face="Menlo"><span style="font-size: 11px;">- Thanks, Fariborz</span></font></div><div><font face="Menlo"><span style="font-size: 11px;"><br></span></font><blockquote type="cite"><br><blockquote type="cite"> def err_objc_bridge_not_cftype : Error<<br>   "'objc_bridge' attribute must be applied to definition of CF types">;<br>-def err_objc_bridge_not_pointert_to_struct : Error<<br>-  "'objc_bridge' attribute must be applied to a pointer to struct type">;<br> def err_objc_cf_bridged_not_interface : Error<<br>   "CF object of type %0 is bridged to '%1', which is not an Objective-C class">;<br> def err_objc_ns_bridged_invalid_cfobject : Error<<br><br>Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=195061&r1=195060&r2=195061&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=195061&r1=195060&r2=195061&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 18 18:09:48 2013<br>@@ -10072,6 +10072,31 @@ void Sema::AddKnownFunctionAttributes(Fu<br>   }<br> }<br><br>+static inline bool isTollFreeBridgeCFRefType(TypedefDecl *TD) {<br>+  TypedefNameDecl * TDefNameDecl = TD;<br></blockquote><br>Extra space surrounding the asterisk.<br><br><blockquote type="cite">+  const Type *TP = TDefNameDecl->getUnderlyingType().getTypePtr();<br>+  while (const TypedefType *TDef = dyn_cast<TypedefType>(TP)) {<br>+    TDefNameDecl = TDef->getDecl();<br>+    TP = TDefNameDecl->getUnderlyingType().getTypePtr();<br>+  }<br>+<br>+  StringRef TDName = TDefNameDecl->getIdentifier()->getName();<br>+  return (TDName.startswith("CF") && TDName.endswith("Ref"));<br>+}<br>+<br>+/// CheckObjCBridgeAttribute - Checks that objc_bridge attribute is<br>+/// properly applied to a typedef of a pointer to struct/union/class<br>+static void CheckObjCBridgeAttribute(Sema &S, TypedefDecl *TD) {<br>+  QualType T = TD->getUnderlyingType();<br>+  if (!T->isPointerType())<br>+    return;<br></blockquote><br>This behavior doesn't match the comments -- if it's not a pointer<br>type, should it not have a diagnostic?<br><br><blockquote type="cite">+  T = T->getPointeeType();<br>+  if (T->isStructureType() || T->isUnionType() || T->isClassType())<br>+    if (RecordDecl *RD = T->getAs<RecordType>()->getDecl())<br>+      if (RD->hasAttr<ObjCBridgeAttr>() && !isTollFreeBridgeCFRefType(TD))<br>+        S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_cftype);<br>+}<br>+<br> TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T,<br>                                     TypeSourceInfo *TInfo) {<br>   assert(D.getIdentifier() && "Wrong callback for declspec without declarator");<br>@@ -10095,6 +10120,8 @@ TypedefDecl *Sema::ParseTypedefDecl(Scop<br>     return NewTD;<br>   }<br><br>+  CheckObjCBridgeAttribute(*this, NewTD);<br></blockquote><br>Why did this functionality move out of SemaDeclAttr.cpp and into SemaDecl.cpp?<br><br><blockquote type="cite">+<br>   if (D.getDeclSpec().isModulePrivateSpecified()) {<br>     if (CurContext->isFunctionOrMethod())<br>       Diag(NewTD->getLocation(), diag::err_module_private_local)<br><br>Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=195061&r1=195060&r2=195061&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=195061&r1=195060&r2=195061&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Nov 18 18:09:48 2013<br>@@ -207,11 +207,6 @@ static inline bool isCFStringType(QualTy<br>   return RD->getIdentifier() == &Ctx.Idents.get("__CFString");<br> }<br><br>-static inline bool isTollFreeBridgeCFRefType(TypedefNameDecl *TD, ASTContext &Ctx) {<br>-  StringRef TDName = TD->getIdentifier()->getName();<br>-  return (TDName.startswith("CF") && TDName.endswith("Ref"));<br>-}<br>-<br> static unsigned getNumAttributeArgs(const AttributeList &Attr) {<br>   // FIXME: Include the type in the argument list.<br>   return Attr.getNumArgs() + Attr.hasParsedType();<br>@@ -4396,34 +4391,7 @@ static void handleNSBridgedAttr(Sema &S,<br><br> static void handleObjCBridgeAttr(Sema &S, Scope *Sc, Decl *D,<br>                                 const AttributeList &Attr) {<br>-  if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {<br>-    QualType T = TD->getUnderlyingType();<br>-    if (T->isPointerType()) {<br>-      T = T->getPointeeType();<br>-      if (T->isRecordType()) {<br>-        RecordDecl *RD = T->getAs<RecordType>()->getDecl();<br>-        if (!RD || RD->isUnion()) {<br>-          S.Diag(D->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)<br>-          << Attr.getRange();<br>-          return;<br>-        }<br>-      } else {<br>-        S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)<br>-        << Attr.getRange();<br>-        return;<br>-      }<br>-    } else {<br>-      S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_pointert_to_struct)<br>-            << Attr.getRange();<br>-      return;<br>-    }<br>-    // Check for T being a CFType goes here.<br>-    if (!isTollFreeBridgeCFRefType(TD, S.Context)) {<br>-      S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_cftype);<br>-      return;<br>-    }<br>-  }<br>-  else {<br>+  if (!isa<RecordDecl>(D)) {<br>     S.Diag(D->getLocStart(), diag::err_objc_bridge_attribute);<br>     return;<br>   }<br><br>Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=195061&r1=195060&r2=195061&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=195061&r1=195060&r2=195061&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Nov 18 18:09:48 2013<br>@@ -3165,15 +3165,26 @@ diagnoseObjCARCConversion(Sema &S, Sourc<br>     << castRange << castExpr->getSourceRange();<br> }<br><br>+static inline ObjCBridgeAttr *getObjCBridgeAttr(const TypedefType *TD) {<br>+  TypedefNameDecl *TDNDecl = TD->getDecl();<br>+  QualType QT = TDNDecl->getUnderlyingType();<br>+  if (QT->isPointerType()) {<br>+    QT = QT->getPointeeType();<br>+    if (QT->isStructureType() || QT->isUnionType() || QT->isClassType())<br>+      if (RecordDecl *RD = QT->getAs<RecordType>()->getDecl())<br>+        if (RD->hasAttr<ObjCBridgeAttr>())<br>+          return RD->getAttr<ObjCBridgeAttr>();<br>+  }<br>+  return 0;<br>+}<br>+<br> static bool CheckObjCBridgeNSCast(Sema &S, QualType castType, Expr *castExpr) {<br>   QualType T = castExpr->getType();<br>   while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {<br>     TypedefNameDecl *TDNDecl = TD->getDecl();<br>-    if (TDNDecl->hasAttr<ObjCBridgeAttr>()) {<br>-      ObjCBridgeAttr *ObjCBAttr = TDNDecl->getAttr<ObjCBridgeAttr>();<br>-      IdentifierInfo *Parm = ObjCBAttr->getBridgedType();<br>-      NamedDecl *Target = 0;<br>-      if (Parm && S.getLangOpts().ObjC1) {<br>+    if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {<br>+      if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {<br>+        NamedDecl *Target = 0;<br>         // Check for an existing type with this name.<br>         LookupResult R(S, DeclarationName(Parm), SourceLocation(),<br>                        Sema::LookupOrdinaryName);<br>@@ -3215,11 +3226,9 @@ static bool CheckObjCBridgeCFCast(Sema &<br>   QualType T = castType;<br>   while (const TypedefType *TD = dyn_cast<TypedefType>(T.getTypePtr())) {<br>     TypedefNameDecl *TDNDecl = TD->getDecl();<br>-    if (TDNDecl->hasAttr<ObjCBridgeAttr>()) {<br>-      ObjCBridgeAttr *ObjCBAttr = TDNDecl->getAttr<ObjCBridgeAttr>();<br>-      IdentifierInfo *Parm = ObjCBAttr->getBridgedType();<br>-      NamedDecl *Target = 0;<br>-      if (Parm && S.getLangOpts().ObjC1) {<br>+    if (ObjCBridgeAttr *ObjCBAttr = getObjCBridgeAttr(TD)) {<br>+      if (IdentifierInfo *Parm = ObjCBAttr->getBridgedType()) {<br>+        NamedDecl *Target = 0;<br>         // Check for an existing type with this name.<br>         LookupResult R(S, DeclarationName(Parm), SourceLocation(),<br>                        Sema::LookupOrdinaryName);<br><br>Modified: cfe/trunk/test/SemaObjC/objcbridge-attribute.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objcbridge-attribute.m?rev=195061&r1=195060&r2=195061&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objcbridge-attribute.m?rev=195061&r1=195060&r2=195061&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/SemaObjC/objcbridge-attribute.m (original)<br>+++ cfe/trunk/test/SemaObjC/objcbridge-attribute.m Mon Nov 18 18:09:48 2013<br>@@ -1,37 +1,41 @@<br> // RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s<br> // <a href="rdar://15454846">rdar://15454846</a><br><br>-typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError))) CFErrorRef; // expected-note 2 {{declared here}}<br>+typedef struct __attribute__ ((objc_bridge(NSError))) __CFErrorRef * CFErrorRef; // expected-note 2 {{declared here}}<br><br>-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}}<br>+typedef struct __attribute__((objc_bridge(12))) __CFMyColor  *CFMyColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}<br><br>-typedef struct __CFArray *  __attribute__ ((objc_bridge)) CFArrayRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}<br>+typedef struct __attribute__ ((objc_bridge)) __CFArray *CFArrayRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}<br><br>-typedef void *  __attribute__ ((objc_bridge(NSURL))) CFURLRef;  // expected-error {{'objc_bridge' attribute must be applied to a pointer to struct type}}<br>+typedef void *  __attribute__ ((objc_bridge(NSURL))) CFURLRef;  // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}}<br><br>-typedef void * CFStringRef __attribute__ ((objc_bridge(NSString))); // expected-error {{'objc_bridge' attribute must be applied to a pointer to struct type}}<br>+typedef void * CFStringRef __attribute__ ((objc_bridge(NSString))); // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}}<br><br>-typedef struct __CFLocale * __attribute__((objc_bridge(NSLocale, NSError))) CFLocaleRef;// expected-error {{use of undeclared identifier 'NSError'}}<br>+typedef struct __attribute__((objc_bridge(NSLocale, NSError))) __CFLocale *CFLocaleRef;// expected-error {{use of undeclared identifier 'NSError'}}<br><br>-typedef struct __CFData __attribute__((objc_bridge(NSData))) CFDataRef; // expected-error {{'objc_bridge' attribute must be applied to a pointer to struct type}}<br>+typedef struct __CFData __attribute__((objc_bridge(NSData))) CFDataRef; // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}}<br><br>-typedef struct __attribute__((objc_bridge(NSDictionary))) __CFDictionary * CFDictionaryRef; // expected-error {{'objc_bridge' attribute must be put on a typedef only}}<br>+typedef struct __attribute__((objc_bridge(NSDictionary))) __CFDictionary * CFDictionaryRef;<br><br>-typedef struct __CFSetRef * CFSetRef __attribute__((objc_bridge(NSSet)));<br>+typedef struct __CFSetRef * CFSetRef __attribute__((objc_bridge(NSSet))); // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}};<br><br>-typedef union __CFUColor * __attribute__((objc_bridge(NSUColor))) CFUColorRef; // expected-error {{'objc_bridge' attribute must be applied to a pointer to struct type}}<br>+typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) * CFUColorRef; // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}};<br>+<br>+typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) *CFUColor1Ref; // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}};<br>+<br>+typedef union __attribute__((objc_bridge(NSUColor))) __CFUPrimeColor XXX;<br>+typedef XXX *CFUColor2Ref;<br><br> @interface I<br> {<br>-   __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute must be put on a typedef only}}<br>-<br>+   __attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute must be applied to a struct, C++ class, or union}};<br> }<br> @end<br><br> @protocol NSTesting @end<br> @class NSString;<br><br>-typedef struct __CFError * __attribute__((objc_bridge(NSTesting))) CFTestingRef; // expected-note {{declared here}}<br>+typedef struct __attribute__((objc_bridge(NSTesting))) __CFError *CFTestingRef; // expected-note {{declared here}}<br><br> id Test1(CFTestingRef cf) {<br>   return (NSString *)cf; // expected-error {{CF object of type 'CFTestingRef' (aka 'struct __CFError *') is bridged to 'NSTesting', which is not an Objective-C class}}<br>@@ -46,14 +50,17 @@ typedef CFErrorRef1 CFErrorRef2;<br> @interface MyError : NSError<br> @end<br><br>+@interface NSUColor @end<br>+<br> @class NSString;<br><br>-void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c) {<br>-  (void)(NSString *)cf; // expected-warning {{CFErrorRef bridges to NSError, not NSString}}<br>+void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c, CFUColor2Ref cf2) {<br>+  (void)(NSString *)cf; // expected-warning {{CFErrorRef2 bridges to NSError, not NSString}}<br>   (void)(NSError *)cf; // okay<br>   (void)(MyError*)cf; // okay,<br>+  (void)(NSUColor *)cf2; // okay<br>   (void)(CFErrorRef)ns; // okay<br>   (void)(CFErrorRef)str;  // expected-warning {{NSString cannot bridge to CFErrorRef}}<br>-  (void)(Class)cf; // expected-warning {{CFErrorRef bridges to NSError, not 'Class'}}<br>+  (void)(Class)cf; // expected-warning {{CFErrorRef2 bridges to NSError, not 'Class'}}<br>   (void)(CFErrorRef)c; // expected-warning {{'Class' cannot bridge to 'CFErrorRef'}}<br> }<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br></blockquote><br>~Aaron<br></blockquote></div><br></body></html>