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">;
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();
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;
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:
--- /dev/null
+// 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