Thanks! Sent from my iPhone
> On Nov 18, 2013, at 5:44 PM, jahanian <[email protected]> wrote: > > In r195066 and r195070. > > - Fariborz > >> On Nov 18, 2013, at 4:27 PM, Douglas Gregor <[email protected]> wrote: >> >> >>> On Nov 18, 2013, at 4:09 PM, Fariborz Jahanian <[email protected]> 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 >>> >>> +@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 >>> [email protected] >>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >> > _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
