r196408 - ObjectiveC - Introducing objc_bridge_related attribute

Fariborz Jahanian fjahanian at apple.com
Wed Dec 4 12:32:50 PST 2013


Author: fjahanian
Date: Wed Dec  4 14:32:50 2013
New Revision: 196408

URL: http://llvm.org/viewvc/llvm-project?rev=196408&view=rev
Log:
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

Added:
    cfe/trunk/test/Parser/objcbridge-related-attribute.m
Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Dec  4 14:32:50 2013
@@ -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]>;

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Wed Dec  4 14:32:50 2013
@@ -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<

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Wed Dec  4 14:32:50 2013
@@ -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,

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Dec  4 14:32:50 2013
@@ -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);
 
@@ -768,6 +802,20 @@ public:
     add(attr);
     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(

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Dec  4 14:32:50 2013
@@ -259,6 +259,12 @@ void Parser::ParseGNUAttributeArgs(Ident
     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(
                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

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=196408&r1=196407&r2=196408&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Dec  4 14:32:50 2013
@@ -3713,6 +3713,24 @@ static void handleObjCBridgeMutableAttr(
                             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
       
   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;

Added: cfe/trunk/test/Parser/objcbridge-related-attribute.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/objcbridge-related-attribute.m?rev=196408&view=auto
==============================================================================
--- cfe/trunk/test/Parser/objcbridge-related-attribute.m (added)
+++ cfe/trunk/test/Parser/objcbridge-related-attribute.m Wed Dec  4 14:32:50 2013
@@ -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 ')'}}
+





More information about the cfe-commits mailing list