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]>;
"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<
SourceLocation AvailabilityLoc,
ParsedAttributes &attrs,
SourceLocation *endLoc);
+
+ void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated,
+ SourceLocation ObjCBridgeRelatedLoc,
+ ParsedAttributes &attrs,
+ SourceLocation *endLoc);
bool IsThreadSafetyAttribute(StringRef AttrName);
void ParseThreadSafetyAttribute(IdentifierInfo &AttrName,
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,
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);
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,
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.
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
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();
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;
--- /dev/null
+// 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 ')'}}
+