ObjectiveC ARC. Introduce a new attribute, 'objc_bridge'
that teaches the compiler about a subset of toll-free bridging semantics. This is wip. // rdar://15454846 llvm-svn: 194633
This commit is contained in:
parent
415ef6db68
commit
0a0a39708c
|
@ -542,6 +542,12 @@ def NSBridged : InheritableAttr {
|
|||
let Args = [IdentifierArgument<"BridgedType", 1>];
|
||||
}
|
||||
|
||||
def ObjCBridge : InheritableAttr {
|
||||
let Spellings = [GNU<"objc_bridge">];
|
||||
let Subjects = [Record];
|
||||
let Args = [IdentifierArgument<"BridgedType", 1>];
|
||||
}
|
||||
|
||||
def NSReturnsRetained : InheritableAttr {
|
||||
let Spellings = [GNU<"ns_returns_retained">];
|
||||
let Subjects = [ObjCMethod, Function];
|
||||
|
|
|
@ -2435,8 +2435,18 @@ def warn_objc_requires_super_protocol : Warning<
|
|||
def note_protocol_decl : Note<
|
||||
"protocol is declared here">;
|
||||
|
||||
// objc_bridge attribute diagnostics.
|
||||
def err_ns_bridged_not_interface : Error<
|
||||
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
|
||||
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">;
|
||||
def err_objc_bridge_not_cftype : Error<
|
||||
"'objc_bridge' attribute must be applied to definition of CF types">;
|
||||
|
||||
def err_objc_bridge_not_pointertype : Error<
|
||||
"'objc_bridge' attribute must be applied to a pointer type">;
|
||||
|
||||
// Function Parameter Semantic Analysis.
|
||||
def err_param_with_void_type : Error<"argument may not have 'void' type">;
|
||||
|
|
|
@ -207,6 +207,12 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) {
|
|||
return RD->getIdentifier() == &Ctx.Idents.get("__CFString");
|
||||
}
|
||||
|
||||
static inline bool isCFRefType(TypedefNameDecl *TD, ASTContext &Ctx) {
|
||||
StringRef TDName = TD->getIdentifier()->getName();
|
||||
return ((TDName.startswith("CF") || TDName.startswith("CG")) &&
|
||||
(TDName.rfind("Ref") != StringRef::npos));
|
||||
}
|
||||
|
||||
static unsigned getNumAttributeArgs(const AttributeList &Attr) {
|
||||
// FIXME: Include the type in the argument list.
|
||||
return Attr.getNumArgs() + Attr.hasParsedType();
|
||||
|
@ -4389,6 +4395,50 @@ static void handleNSBridgedAttr(Sema &S, Scope *Sc, Decl *D,
|
|||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
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_attribute_wrong_decl_type)
|
||||
<< Attr.getRange() << Attr.getName() << ExpectedStruct;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_pointertype);
|
||||
return;
|
||||
}
|
||||
// Check for T being a CFType goes here.
|
||||
if (!isCFRefType(TD, S.Context)) {
|
||||
S.Diag(TD->getLocStart(), diag::err_objc_bridge_not_cftype);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
S.Diag(D->getLocStart(), diag::err_objc_bridge_attribute);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Attr.getNumArgs() != 1) {
|
||||
S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
|
||||
return;
|
||||
}
|
||||
IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
|
||||
if (!Parm) {
|
||||
S.Diag(D->getLocStart(), diag::err_objc_bridge_not_id);
|
||||
return;
|
||||
}
|
||||
|
||||
D->addAttr(::new (S.Context)
|
||||
ObjCBridgeAttr(Attr.getRange(), S.Context, Parm ? Parm->Ident : 0,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
if (hasDeclarator(D)) return;
|
||||
|
@ -4676,6 +4726,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
case AttributeList::AT_NSBridged:
|
||||
handleNSBridgedAttr(S, scope, D, Attr); break;
|
||||
|
||||
case AttributeList::AT_ObjCBridge:
|
||||
handleObjCBridgeAttr(S, scope, D, Attr); break;
|
||||
|
||||
case AttributeList::AT_CFAuditedTransfer:
|
||||
case AttributeList::AT_CFUnknownTransfer:
|
||||
handleCFTransferAttr(S, D, Attr); break;
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
|
||||
// rdar://15454846
|
||||
|
||||
typedef struct CGColor * __attribute__ ((objc_bridge(NSError))) CGColorRef;
|
||||
|
||||
typedef struct CGColor * __attribute__((objc_bridge(12))) CFMyColorRef; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}
|
||||
|
||||
typedef struct S1 * __attribute__ ((objc_bridge)) CGColorRef1; // expected-error {{parameter of 'objc_bridge' attribute must be a single name of an Objective-C class}}
|
||||
|
||||
typedef void * __attribute__ ((objc_bridge(NSString))) CGColorRef2;
|
||||
|
||||
typedef void * CFTypeRef __attribute__ ((objc_bridge(NSError)));
|
||||
|
||||
typedef struct CGColor * __attribute__((objc_bridge(NSString, NSError))) CGColorRefNoNSObject;// expected-error {{use of undeclared identifier 'NSError'}}
|
||||
|
||||
typedef struct CGColor __attribute__((objc_bridge(NSError))) CGColorRefNoNSObject2; // expected-error {{'objc_bridge' attribute must be applied to a pointer type}}
|
||||
|
||||
typedef struct __attribute__((objc_bridge(NSError))) CFColor * CFColorRefNoNSObject; // expected-error {{'objc_bridge' attribute must be put on a typedef only}}
|
||||
|
||||
typedef struct __attribute__((objc_bridge(NSError))) CFColor * CFColorRefNoNSObject1;
|
||||
|
||||
typedef union CFUColor * __attribute__((objc_bridge(NSError))) CFColorRefNoNSObject2; // expected-error {{'objc_bridge' attribute only applies to structs}}
|
||||
|
||||
@interface I
|
||||
{
|
||||
__attribute__((objc_bridge(NSError))) void * color; // expected-error {{'objc_bridge' attribute must be put on a typedef only}}
|
||||
|
||||
}
|
||||
@end
|
Loading…
Reference in New Issue