r195061 - ObjectiveC ARC. Adopt objc_bridge attribute

Aaron Ballman aaron at aaronballman.com
Tue Nov 19 10:05:41 PST 2013


Thanks!  Looks good!

~Aaron

On Tue, Nov 19, 2013 at 12:50 PM, jahanian <fjahanian at apple.com> wrote:
>
> On Nov 18, 2013, at 5:24 PM, Aaron Ballman <aaron at aaronballman.com> wrote:
>
> On Mon, Nov 18, 2013 at 7:09 PM, Fariborz Jahanian <fjahanian at apple.com>
> wrote:
>
> Author: fjahanian
> Date: Mon Nov 18 18:09:48 2013
> New Revision: 195061
>
> URL: http://llvm.org/viewvc/llvm-project?rev=195061&view=rev
> Log:
> ObjectiveC ARC. Adopt objc_bridge attribute
> on struct/union/class instead of typedef of
> such types. // rdar://15454846
>
> Modified:
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>    cfe/trunk/lib/Sema/SemaDecl.cpp
>    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>    cfe/trunk/lib/Sema/SemaExprObjC.cpp
>    cfe/trunk/test/SemaObjC/objcbridge-attribute.m
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=195061&r1=195060&r2=195061&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Nov 18 18:09:48
> 2013
> @@ -2442,11 +2442,9 @@ def err_ns_bridged_not_interface : Error
> def err_objc_bridge_not_id : Error<
>   "parameter of 'objc_bridge' attribute must be a single name of an
> Objective-C class">;
> def err_objc_bridge_attribute : Error<
> -  "'objc_bridge' attribute must be put on a typedef only">;
> +  "'objc_bridge' attribute must be applied to a struct, C++ class, or
> union">;
>
>
> Please use err_attribute_wrong_decl_type instead of a custom error message.
>
>
> In r195135. Also, per Doug’s comment earlier, I removed the two routines you
> had
> comments on.
>
> - Thanks, Fariborz
>
>
> 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_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<
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=195061&r1=195060&r2=195061&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Nov 18 18:09:48 2013
> @@ -10072,6 +10072,31 @@ void Sema::AddKnownFunctionAttributes(Fu
>   }
> }
>
> +static inline bool isTollFreeBridgeCFRefType(TypedefDecl *TD) {
> +  TypedefNameDecl * TDefNameDecl = TD;
>
>
> Extra space surrounding the asterisk.
>
> +  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;
>
>
> This behavior doesn't match the comments -- if it's not a pointer
> type, should it not have a diagnostic?
>
> +  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 @@ TypedefDecl *Sema::ParseTypedefDecl(Scop
>     return NewTD;
>   }
>
> +  CheckObjCBridgeAttribute(*this, NewTD);
>
>
> Why did this functionality move out of SemaDeclAttr.cpp and into
> SemaDecl.cpp?
>
> +
>   if (D.getDeclSpec().isModulePrivateSpecified()) {
>     if (CurContext->isFunctionOrMethod())
>       Diag(NewTD->getLocation(), diag::err_module_private_local)
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=195061&r1=195060&r2=195061&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Nov 18 18:09:48 2013
> @@ -207,11 +207,6 @@ static inline bool isCFStringType(QualTy
>   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 handleNSBridgedAttr(Sema &S,
>
> 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;
>   }
>
> Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=195061&r1=195060&r2=195061&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Mon Nov 18 18:09:48 2013
> @@ -3165,15 +3165,26 @@ diagnoseObjCARCConversion(Sema &S, Sourc
>     << 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 @@ static bool CheckObjCBridgeCFCast(Sema &
>   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);
>
> Modified: cfe/trunk/test/SemaObjC/objcbridge-attribute.m
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/objcbridge-attribute.m?rev=195061&r1=195060&r2=195061&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/objcbridge-attribute.m (original)
> +++ cfe/trunk/test/SemaObjC/objcbridge-attribute.m Mon Nov 18 18:09:48 2013
> @@ -1,37 +1,41 @@
> // RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -Wno-objc-root-class %s
> // rdar://15454846
>
> -typedef struct __CFErrorRef * __attribute__ ((objc_bridge(NSError)))
> CFErrorRef; // expected-note 2 {{declared here}}
> +typedef struct __attribute__ ((objc_bridge(NSError))) __CFErrorRef *
> CFErrorRef; // expected-note 2 {{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}}
> +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}}
>
> -typedef struct __CFArray *  __attribute__ ((objc_bridge)) CFArrayRef; //
> expected-error {{parameter of 'objc_bridge' attribute must be a single name
> of an Objective-C class}}
> +typedef struct __attribute__ ((objc_bridge)) __CFArray *CFArrayRef; //
> expected-error {{parameter of 'objc_bridge' attribute must be a single name
> of an Objective-C class}}
>
> -typedef void *  __attribute__ ((objc_bridge(NSURL))) CFURLRef;  //
> expected-error {{'objc_bridge' attribute must be applied to a pointer to
> struct type}}
> +typedef void *  __attribute__ ((objc_bridge(NSURL))) CFURLRef;  //
> expected-error {{'objc_bridge' attribute must be applied to a struct, C++
> class, or union}}
>
> -typedef void * CFStringRef __attribute__ ((objc_bridge(NSString))); //
> expected-error {{'objc_bridge' attribute must be applied to a pointer to
> struct type}}
> +typedef void * CFStringRef __attribute__ ((objc_bridge(NSString))); //
> expected-error {{'objc_bridge' attribute must be applied to a struct, C++
> class, or union}}
>
> -typedef struct __CFLocale * __attribute__((objc_bridge(NSLocale, NSError)))
> CFLocaleRef;// expected-error {{use of undeclared identifier 'NSError'}}
> +typedef struct __attribute__((objc_bridge(NSLocale, NSError))) __CFLocale
> *CFLocaleRef;// expected-error {{use of undeclared identifier 'NSError'}}
>
> -typedef struct __CFData __attribute__((objc_bridge(NSData))) CFDataRef; //
> expected-error {{'objc_bridge' attribute must be applied to a pointer to
> struct type}}
> +typedef struct __CFData __attribute__((objc_bridge(NSData))) CFDataRef; //
> expected-error {{'objc_bridge' attribute must be applied to a struct, C++
> class, or union}}
>
> -typedef struct __attribute__((objc_bridge(NSDictionary))) __CFDictionary *
> CFDictionaryRef; // expected-error {{'objc_bridge' attribute must be put on
> a typedef only}}
> +typedef struct __attribute__((objc_bridge(NSDictionary))) __CFDictionary *
> CFDictionaryRef;
>
> -typedef struct __CFSetRef * CFSetRef __attribute__((objc_bridge(NSSet)));
> +typedef struct __CFSetRef * CFSetRef __attribute__((objc_bridge(NSSet)));
> // expected-error {{'objc_bridge' attribute must be applied to a struct, C++
> class, or union}};
>
> -typedef union __CFUColor * __attribute__((objc_bridge(NSUColor)))
> CFUColorRef; // expected-error {{'objc_bridge' attribute must be applied to
> a pointer to struct type}}
> +typedef union __CFUColor __attribute__((objc_bridge(NSUColor))) *
> CFUColorRef; // expected-error {{'objc_bridge' attribute must be applied to
> a struct, C++ class, or union}};
> +
> +typedef union __CFUColor __attribute__((objc_bridge(NSUColor)))
> *CFUColor1Ref; // expected-error {{'objc_bridge' attribute must be applied
> to a struct, C++ class, or union}};
> +
> +typedef union __attribute__((objc_bridge(NSUColor))) __CFUPrimeColor XXX;
> +typedef XXX *CFUColor2Ref;
>
> @interface I
> {
> -   __attribute__((objc_bridge(NSError))) void * color; // expected-error
> {{'objc_bridge' attribute must be put on a typedef only}}
> -
> +   __attribute__((objc_bridge(NSError))) void * color; // expected-error
> {{'objc_bridge' attribute must be applied to a struct, C++ class, or
> union}};
> }
> @end
>
> @protocol NSTesting @end
> @class NSString;
>
> -typedef struct __CFError * __attribute__((objc_bridge(NSTesting)))
> CFTestingRef; // expected-note {{declared here}}
> +typedef struct __attribute__((objc_bridge(NSTesting))) __CFError
> *CFTestingRef; // expected-note {{declared here}}
>
> id Test1(CFTestingRef cf) {
>   return (NSString *)cf; // expected-error {{CF object of type
> 'CFTestingRef' (aka 'struct __CFError *') is bridged to 'NSTesting', which
> is not an Objective-C class}}
> @@ -46,14 +50,17 @@ typedef CFErrorRef1 CFErrorRef2;
> @interface MyError : NSError
> @end
>
> + at interface NSUColor @end
> +
> @class NSString;
>
> -void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c) {
> -  (void)(NSString *)cf; // expected-warning {{CFErrorRef bridges to
> NSError, not NSString}}
> +void Test2(CFErrorRef2 cf, NSError *ns, NSString *str, Class c,
> CFUColor2Ref cf2) {
> +  (void)(NSString *)cf; // expected-warning {{CFErrorRef2 bridges to
> NSError, not NSString}}
>   (void)(NSError *)cf; // okay
>   (void)(MyError*)cf; // okay,
> +  (void)(NSUColor *)cf2; // okay
>   (void)(CFErrorRef)ns; // okay
>   (void)(CFErrorRef)str;  // expected-warning {{NSString cannot bridge to
> CFErrorRef}}
> -  (void)(Class)cf; // expected-warning {{CFErrorRef bridges to NSError, not
> 'Class'}}
> +  (void)(Class)cf; // expected-warning {{CFErrorRef2 bridges to NSError,
> not 'Class'}}
>   (void)(CFErrorRef)c; // expected-warning {{'Class' cannot bridge to
> 'CFErrorRef'}}
> }
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
>
> ~Aaron
>
>




More information about the cfe-commits mailing list