summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/Type.h1
-rw-r--r--clang/include/clang/Basic/Attr.td5
-rw-r--r--clang/include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td8
-rw-r--r--clang/lib/AST/Type.cpp5
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp19
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp5
-rw-r--r--clang/test/SemaObjC/psuedo-class-attribute.m36
8 files changed, 78 insertions, 2 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 5db43b4cfc4..6eb94405b95 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -1575,6 +1575,7 @@ public:
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)
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 05a399afda9..423fdc67847 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -1058,6 +1058,11 @@ def ObjCNSObject : InheritableAttr {
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>;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 5e4d7efa982..09c50a959cb 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -394,6 +394,7 @@ def IgnoredPragmas : DiagGroup<"ignored-pragmas">;
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,
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 89b439c7c31..6199aebc952 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2200,6 +2200,14 @@ def warn_gc_attribute_weak_on_local : Warning<
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">,
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 0e8b1e81197..0eb5d8c338c 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2371,6 +2371,11 @@ bool Type::isObjCNSObjectType() const {
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() ||
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index fa61b974e04..756b2d68a55 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -2122,6 +2122,22 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
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)
@@ -4678,6 +4694,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
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;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 256419353c8..dc47ce966f7 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -3299,7 +3299,7 @@ Decl *Sema::ActOnMethodDeclaration(
case OMF_alloc:
case OMF_new:
- InferRelatedResultType = ObjCMethod->isClassMethod();
+ InferRelatedResultType = ObjCMethod->isClassMethod();
break;
case OMF_init:
@@ -3310,7 +3310,8 @@ Decl *Sema::ActOnMethodDeclaration(
break;
}
- if (InferRelatedResultType)
+ if (InferRelatedResultType &&
+ !ObjCMethod->getReturnType()->isObjCIndependentClassType())
ObjCMethod->SetRelatedResultType();
}
diff --git a/clang/test/SemaObjC/psuedo-class-attribute.m b/clang/test/SemaObjC/psuedo-class-attribute.m
new file mode 100644
index 00000000000..c6ba077959f
--- /dev/null
+++ b/clang/test/SemaObjC/psuedo-class-attribute.m
@@ -0,0 +1,36 @@
+// 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;
+}
OpenPOWER on IntegriCloud