r195061 - ObjectiveC ARC. Adopt objc_bridge attribute

Douglas Gregor dgregor at apple.com
Mon Nov 18 19:16:18 PST 2013


Thanks!

Sent from my iPhone

> On Nov 18, 2013, at 5:44 PM, jahanian <fjahanian at apple.com> wrote:
> 
> In r195066 and r195070.
> 
> - Fariborz
> 
>> On Nov 18, 2013, at 4:27 PM, Douglas Gregor <dgregor at apple.com> wrote:
>> 
>> 
>>> On Nov 18, 2013, at 4: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”>;
>> 
>> Nit: could you %select{|, C++ class}0 based on getLangOpts().CPlusPlus, so that we don’t say “C++ class” in non-C++ code?
>> 
>>> 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;
>>> +  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"));
>>> +}
>> 
>> We shouldn’t be performing the name check here. Some CF-like types might not be named CF*Ref, and this attribute is specific enough that we can trust the user to only put it on structs where it makes sense.
>> 
>>> +/// 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 @@ TypedefDecl *Sema::ParseTypedefDecl(Scop
>>>   return NewTD;
>>> }
>>> 
>>> +  CheckObjCBridgeAttribute(*this, NewTD);
>>> +  
>>> 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())
>> 
>> How about
>> 
>>    if (const RecordType *RT = QT->getAs<RecordType>())
>> 
>> ?
>> 
>> 
>>> +      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
>> 
> 




More information about the cfe-commits mailing list