Le 19 nov. 2013 à 01:27, Douglas Gregor <dgre...@apple.com> a écrit :
> > On Nov 18, 2013, at 4:09 PM, Fariborz Jahanian <fjahan...@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. You're right, for instance AddressBook Framework provides such types: ABAddressBookRef -> ABAddressBook, … >> +/// 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 >> cfe-commits@cs.uiuc.edu >> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits -- Jean-Daniel _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits