forked from OSchip/llvm-project
ObjectiveC - Introducing objc_bridge_related attribute
which specifies couple of (optional) method selectors for bridging a CFobject to or from an ObjectiveC object. This is wip. // rdsr://15499111 llvm-svn: 196408
This commit is contained in:
parent
17c357342a
commit
1a2519a7e9
|
@ -615,6 +615,15 @@ def ObjCBridgeMutable : InheritableAttr {
|
|||
let Args = [IdentifierArgument<"BridgedType">];
|
||||
}
|
||||
|
||||
def ObjCBridgeRelated : InheritableAttr {
|
||||
let Spellings = [GNU<"objc_bridge_related">];
|
||||
let Subjects = SubjectList<[Record], ErrorDiag>;
|
||||
let Args = [IdentifierArgument<"RelatedClass">,
|
||||
IdentifierArgument<"ClassMethod">,
|
||||
IdentifierArgument<"InstanceMethod">];
|
||||
let HasCustomParsing = 1;
|
||||
}
|
||||
|
||||
def NSReturnsRetained : InheritableAttr {
|
||||
let Spellings = [GNU<"ns_returns_retained">];
|
||||
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
|
||||
|
|
|
@ -753,6 +753,13 @@ def err_zero_version : Error<
|
|||
"version number must have non-zero major, minor, or sub-minor version">;
|
||||
def err_availability_expected_platform : Error<
|
||||
"expected a platform name, e.g., 'macosx'">;
|
||||
|
||||
// objc_bridge_related attribute
|
||||
def err_objcbridge_related_expected_related_class : Error<
|
||||
"expected a related ObjectiveC class name, e.g., 'NSColor'">;
|
||||
def err_objcbridge_related_selector_name : Error<
|
||||
"expected a class method selector with single argument, e.g., 'colorWithCGColor:'">;
|
||||
|
||||
def err_availability_expected_change : Error<
|
||||
"expected 'introduced', 'deprecated', or 'obsoleted'">;
|
||||
def err_availability_unknown_change : Error<
|
||||
|
|
|
@ -2003,6 +2003,11 @@ private:
|
|||
SourceLocation AvailabilityLoc,
|
||||
ParsedAttributes &attrs,
|
||||
SourceLocation *endLoc);
|
||||
|
||||
void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
|
||||
SourceLocation ObjCBridgeRelatedLoc,
|
||||
ParsedAttributes &attrs,
|
||||
SourceLocation *endLoc);
|
||||
|
||||
bool IsThreadSafetyAttribute(StringRef AttrName);
|
||||
void ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
|
||||
|
|
|
@ -245,6 +245,26 @@ private:
|
|||
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
|
||||
}
|
||||
|
||||
/// Constructor for objc_bridge_related attributes.
|
||||
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierLoc *Parm1,
|
||||
IdentifierLoc *Parm2,
|
||||
IdentifierLoc *Parm3,
|
||||
Syntax syntaxUsed)
|
||||
: AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange),
|
||||
ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed),
|
||||
Invalid(false), UsedAsTypeAttr(false), IsAvailability(false),
|
||||
IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false),
|
||||
NextInPosition(0), NextInPool(0) {
|
||||
ArgsVector Args;
|
||||
Args.push_back(Parm1);
|
||||
Args.push_back(Parm2);
|
||||
Args.push_back(Parm3);
|
||||
memcpy(getArgsBuffer(), &Args[0], 3 * sizeof(ArgsUnion));
|
||||
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
|
||||
}
|
||||
|
||||
/// Constructor for type_tag_for_datatype attribute.
|
||||
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
|
@ -609,6 +629,20 @@ public:
|
|||
syntax));
|
||||
}
|
||||
|
||||
AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierLoc *Param1,
|
||||
IdentifierLoc *Param2,
|
||||
IdentifierLoc *Param3,
|
||||
AttributeList::Syntax syntax) {
|
||||
size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion);
|
||||
void *memory = allocate(size);
|
||||
return add(new (memory) AttributeList(attrName, attrRange,
|
||||
scopeName, scopeLoc,
|
||||
Param1, Param2, Param3,
|
||||
syntax));
|
||||
}
|
||||
|
||||
AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name,
|
||||
SourceLocation TokLoc, int Arg);
|
||||
|
||||
|
@ -769,6 +803,20 @@ public:
|
|||
return attr;
|
||||
}
|
||||
|
||||
/// Add objc_bridge_related attribute.
|
||||
AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierLoc *Param1,
|
||||
IdentifierLoc *Param2,
|
||||
IdentifierLoc *Param3,
|
||||
AttributeList::Syntax syntax) {
|
||||
AttributeList *attr =
|
||||
pool.create(attrName, attrRange, scopeName, scopeLoc,
|
||||
Param1, Param2, Param3, syntax);
|
||||
add(attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
/// Add type_tag_for_datatype attribute.
|
||||
AttributeList *addNewTypeTagForDatatype(
|
||||
IdentifierInfo *attrName, SourceRange attrRange,
|
||||
|
|
|
@ -259,6 +259,12 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
|
|||
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AttrKind == AttributeList::AT_ObjCBridgeRelated) {
|
||||
ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc);
|
||||
return;
|
||||
}
|
||||
|
||||
// Thread safety attributes are parsed in an unevaluated context.
|
||||
// FIXME: Share the bulk of the parsing code here and just pull out
|
||||
// the unevaluated context.
|
||||
|
@ -959,6 +965,90 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability,
|
|||
AttributeList::AS_GNU);
|
||||
}
|
||||
|
||||
/// \brief Parse the contents of the "objc_bridge_related" attribute.
|
||||
/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'
|
||||
/// related_class:
|
||||
/// Identifier
|
||||
///
|
||||
/// opt-class_method:
|
||||
/// Identifier: | <empty>
|
||||
///
|
||||
/// opt-instance_method:
|
||||
/// Identifier | <empty>
|
||||
///
|
||||
void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
|
||||
SourceLocation ObjCBridgeRelatedLoc,
|
||||
ParsedAttributes &attrs,
|
||||
SourceLocation *endLoc) {
|
||||
// Opening '('.
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren);
|
||||
if (T.consumeOpen()) {
|
||||
Diag(Tok, diag::err_expected_lparen);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse the related class name.
|
||||
if (Tok.isNot(tok::identifier)) {
|
||||
Diag(Tok, diag::err_objcbridge_related_expected_related_class);
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return;
|
||||
}
|
||||
IdentifierLoc *RelatedClass = ParseIdentifierLoc();
|
||||
if (Tok.isNot(tok::comma)) {
|
||||
Diag(Tok, diag::err_expected_comma);
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return;
|
||||
}
|
||||
ConsumeToken();
|
||||
|
||||
// Parse optional class method name.
|
||||
IdentifierLoc *ClassMethod = 0;
|
||||
if (Tok.is(tok::identifier)) {
|
||||
ClassMethod = ParseIdentifierLoc();
|
||||
if (Tok.isNot(tok::colon)) {
|
||||
Diag(Tok, diag::err_objcbridge_related_selector_name);
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return;
|
||||
}
|
||||
ConsumeToken();
|
||||
}
|
||||
if (Tok.isNot(tok::comma)) {
|
||||
if (Tok.is(tok::colon))
|
||||
Diag(Tok, diag::err_objcbridge_related_selector_name);
|
||||
else
|
||||
Diag(Tok, diag::err_expected_comma);
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return;
|
||||
}
|
||||
ConsumeToken();
|
||||
|
||||
// Parse optional instance method name.
|
||||
IdentifierLoc *InstanceMethod = 0;
|
||||
if (Tok.is(tok::identifier))
|
||||
InstanceMethod = ParseIdentifierLoc();
|
||||
else if (Tok.isNot(tok::r_paren)) {
|
||||
Diag(Tok, diag::err_expected_rparen);
|
||||
SkipUntil(tok::r_paren, StopAtSemi);
|
||||
return;
|
||||
}
|
||||
|
||||
// Closing ')'.
|
||||
if (T.consumeClose())
|
||||
return;
|
||||
|
||||
if (endLoc)
|
||||
*endLoc = T.getCloseLocation();
|
||||
|
||||
// Record this attribute
|
||||
attrs.addNew(&ObjCBridgeRelated,
|
||||
SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),
|
||||
0, ObjCBridgeRelatedLoc,
|
||||
RelatedClass,
|
||||
ClassMethod,
|
||||
InstanceMethod,
|
||||
AttributeList::AS_GNU);
|
||||
|
||||
}
|
||||
|
||||
// Late Parsed Attributes:
|
||||
// See other examples of late parsing in lib/Parse/ParseCXXInlineMethods
|
||||
|
|
|
@ -3713,6 +3713,24 @@ static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
|
|||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleObjCBridgeRelatedAttr(Sema &S, Scope *Sc, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
IdentifierInfo *RelatedClass =
|
||||
Attr.isArgIdent(0) ? Attr.getArgAsIdent(0)->Ident : 0;
|
||||
if (!RelatedClass) {
|
||||
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 0;
|
||||
return;
|
||||
}
|
||||
IdentifierInfo *ClassMethod =
|
||||
Attr.getArgAsIdent(1) ? Attr.getArgAsIdent(1)->Ident : 0;
|
||||
IdentifierInfo *InstanceMethod =
|
||||
Attr.getArgAsIdent(2) ? Attr.getArgAsIdent(2)->Ident : 0;
|
||||
D->addAttr(::new (S.Context)
|
||||
ObjCBridgeRelatedAttr(Attr.getRange(), S.Context, RelatedClass,
|
||||
ClassMethod, InstanceMethod,
|
||||
Attr.getAttributeSpellingListIndex()));
|
||||
}
|
||||
|
||||
static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
|
||||
const AttributeList &Attr) {
|
||||
SourceLocation Loc = Attr.getLoc();
|
||||
|
@ -3986,6 +4004,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
|
||||
case AttributeList::AT_ObjCBridgeMutable:
|
||||
handleObjCBridgeMutableAttr(S, scope, D, Attr); break;
|
||||
|
||||
case AttributeList::AT_ObjCBridgeRelated:
|
||||
handleObjCBridgeRelatedAttr(S, scope, D, Attr); break;
|
||||
|
||||
case AttributeList::AT_ObjCDesignatedInitializer:
|
||||
handleObjCDesignatedInitializer(S, D, Attr); break;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// RUN: %clang_cc1 -verify -fsyntax-only %s
|
||||
// rdar://15499111
|
||||
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,CGColor))) CGColor *CGColorRefOk;
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,,CGColor))) CGColor *CGColorRef1Ok;
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,,))) CGColor *CGColorRef2Ok;
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,))) CGColor *CGColorRef3Ok;
|
||||
|
||||
typedef struct __attribute__((objc_bridge_related(,colorWithCGColor:,CGColor))) CGColor *CGColorRef1NotOk; // expected-error {{expected a related ObjectiveC class name, e.g., 'NSColor'}}
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor,CGColor))) CGColor *CGColorRef2NotOk; // expected-error {{expected a class method selector with single argument, e.g., 'colorWithCGColor:'}}
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor::,CGColor))) CGColor *CGColorRef3NotOk; // expected-error {{expected a class method selector with single argument, e.g., 'colorWithCGColor:'}}
|
||||
typedef struct __attribute__((objc_bridge_related(12,colorWithCGColor:,CGColor))) CGColor *CGColorRef4NotOk; // expected-error {{expected a related ObjectiveC class name, e.g., 'NSColor'}}
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,+:,CGColor))) CGColor *CGColorRef5NotOk; // expected-error {{expected ','}}
|
||||
typedef struct __attribute__((objc_bridge_related(NSColor,colorWithCGColor:,+))) CGColor *CGColorRef6NotOk; // expected-error {{expected ')'}}
|
||||
|
Loading…
Reference in New Issue