bool isObjCLifetimeType() const; // (array of)* retainable type
bool isObjCIndirectLifetimeType() const; // (pointer to)* lifetime type
bool isObjCNSObjectType() const; // __attribute__((NSObject))
+ bool isObjCIndependentClassType() const; // __attribute__((IndependentClass))
// FIXME: change this to 'raw' interface type, so we can used 'interface' type
// for the common case.
bool isObjCObjectType() const; // NSString or typeof(*(id)0)
let Documentation = [Undocumented];
}
+def ObjCIndependentClass : InheritableAttr {
+ let Spellings = [GNU<"IndependentClass">];
+ let Documentation = [Undocumented];
+}
+
def ObjCPreciseLifetime : InheritableAttr {
let Spellings = [GNU<"objc_precise_lifetime">];
let Subjects = SubjectList<[Var], ErrorDiag>;
def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas]>;
def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
+def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
def UnknownAttributes : DiagGroup<"unknown-attributes">;
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
def Attributes : DiagGroup<"attributes", [UnknownAttributes,
def warn_nsobject_attribute : Warning<
"'NSObject' attribute may be put on a typedef only; attribute is ignored">,
InGroup<NSobjectAttribute>;
+def warn_independentclass_attribute : Warning<
+ "'IndependentClass' attribute may be put on a typedef only; "
+ "attribute is ignored">,
+ InGroup<IndependentClassAttribute>;
+def warn_ptr_independentclass_attribute : Warning<
+ "'IndependentClass' attribute may be put on Objective-C object "
+ "pointer type only; attribute is ignored">,
+ InGroup<IndependentClassAttribute>;
def warn_attribute_weak_on_local : Warning<
"__weak attribute cannot be specified on an automatic variable when ARC "
"is not enabled">,
return typedefType->getDecl()->hasAttr<ObjCNSObjectAttr>();
return false;
}
+bool Type::isObjCIndependentClassType() const {
+ if (const TypedefType *typedefType = dyn_cast<TypedefType>(this))
+ return typedefType->getDecl()->hasAttr<ObjCIndependentClassAttr>();
+ return false;
+}
bool Type::isObjCRetainableType() const {
return isObjCObjectPointerType() ||
isBlockPointerType() ||
Attr.getAttributeSpellingListIndex()));
}
+static void handleObjCIndependentClass(Sema &S, Decl *D, const AttributeList &Attr) {
+ if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
+ QualType T = TD->getUnderlyingType();
+ if (!T->isObjCObjectPointerType()) {
+ S.Diag(TD->getLocation(), diag::warn_ptr_independentclass_attribute);
+ return;
+ }
+ } else {
+ S.Diag(D->getLocation(), diag::warn_independentclass_attribute);
+ return;
+ }
+ D->addAttr(::new (S.Context)
+ ObjCIndependentClassAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleBlocksAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
case AttributeList::AT_ObjCNSObject:
handleObjCNSObject(S, D, Attr);
break;
+ case AttributeList::AT_ObjCIndependentClass:
+ handleObjCIndependentClass(S, D, Attr);
+ break;
case AttributeList::AT_Blocks:
handleBlocksAttr(S, D, Attr);
break;
case OMF_alloc:
case OMF_new:
- InferRelatedResultType = ObjCMethod->isClassMethod();
+ InferRelatedResultType = ObjCMethod->isClassMethod();
break;
case OMF_init:
break;
}
- if (InferRelatedResultType)
+ if (InferRelatedResultType &&
+ !ObjCMethod->getReturnType()->isObjCIndependentClassType())
ObjCMethod->SetRelatedResultType();
}
--- /dev/null
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// rdar://20255473
+
+@interface NSObject @end
+
+typedef NSObject * __attribute__((IndependentClass))dispatch_queue_t;
+
+typedef struct S {int ii; } * __attribute__((IndependentClass))dispatch_queue_t_2; // expected-warning {{Objective-C object}}
+
+typedef struct { // expected-warning {{'IndependentClass' attribute may be put on a typedef only; attribute is ignored}}
+ NSObject *__attribute__((IndependentClass)) ns; // expected-warning {{'IndependentClass' attribute may be put on a typedef only; attribute is ignored}}
+} __attribute__((IndependentClass)) T;
+
+dispatch_queue_t dispatch_queue_create();
+
+@interface DispatchQPointerCastIssue : NSObject {
+ NSObject *__attribute__((IndependentClass)) Ivar; // expected-warning {{'IndependentClass' attribute may be put on a typedef only; attribute is ignored}}
+}
+
+@property (copy) NSObject *__attribute__((IndependentClass)) Prop; // expected-warning {{'IndependentClass' attribute may be put on a typedef only; attribute is ignored}}
+
+typedef NSObject * __attribute__((IndependentClass))dispatch_queue_t_1;
+
+@end
+
+@implementation DispatchQPointerCastIssue
++ (dispatch_queue_t) newDispatchQueue {
+ return dispatch_queue_create();
+}
+@end
+
+NSObject *get_nsobject() {
+ typedef NSObject * __attribute__((IndependentClass))dispatch_queue_t;
+ dispatch_queue_t dt;
+ return dt;
+}