diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-12-04 20:32:50 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-12-04 20:32:50 +0000 |
commit | 1a2519a7e9743825dd19c5e958040b3350791b64 (patch) | |
tree | ba2b8bbaa9385199c85da067826ce3b7382611ae /clang/lib | |
parent | 17c357342a7397aca0710613b72139a7256836f8 (diff) | |
download | bcm5719-llvm-1a2519a7e9743825dd19c5e958040b3350791b64.tar.gz bcm5719-llvm-1a2519a7e9743825dd19c5e958040b3350791b64.zip |
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
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 90 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 21 |
2 files changed, 111 insertions, 0 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 944942658ab..2c93def4c2b 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -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 diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c587452aeb4..5414453efc1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -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; |