From e8d60ed0efed466103489cf893bd8bcc32d5dfa7 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Thu, 16 Apr 2015 18:38:44 +0000 Subject: [PATCH] [Objective-C Sema] patch to introduce IndependentClass attribute to be placed on Objective-C pointer typedef to make them strong enough so on their "new" method family no attempt is made to override these types. rdar://20255473 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@235128 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 1 + include/clang/Basic/Attr.td | 5 +++ include/clang/Basic/DiagnosticGroups.td | 1 + include/clang/Basic/DiagnosticSemaKinds.td | 8 +++++ lib/AST/Type.cpp | 5 +++ lib/Sema/SemaDeclAttr.cpp | 19 ++++++++++++ lib/Sema/SemaDeclObjC.cpp | 5 +-- test/SemaObjC/psuedo-class-attribute.m | 36 ++++++++++++++++++++++ 8 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test/SemaObjC/psuedo-class-attribute.m diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 5db43b4cfc..6eb94405b9 100644 --- a/include/clang/AST/Type.h +++ b/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/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 05a399afda..423fdc6784 100644 --- a/include/clang/Basic/Attr.td +++ b/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/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 5e4d7efa98..09c50a959c 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 89b439c7c3..6199aebc95 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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; +def warn_independentclass_attribute : Warning< + "'IndependentClass' attribute may be put on a typedef only; " + "attribute is ignored">, + InGroup; +def warn_ptr_independentclass_attribute : Warning< + "'IndependentClass' attribute may be put on Objective-C object " + "pointer type only; attribute is ignored">, + InGroup; def warn_attribute_weak_on_local : Warning< "__weak attribute cannot be specified on an automatic variable when ARC " "is not enabled">, diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0e8b1e8119..0eb5d8c338 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2371,6 +2371,11 @@ bool Type::isObjCNSObjectType() const { return typedefType->getDecl()->hasAttr(); return false; } +bool Type::isObjCIndependentClassType() const { + if (const TypedefType *typedefType = dyn_cast(this)) + return typedefType->getDecl()->hasAttr(); + return false; +} bool Type::isObjCRetainableType() const { return isObjCObjectPointerType() || isBlockPointerType() || diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index fa61b974e0..756b2d68a5 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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(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/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 256419353c..dc47ce966f 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/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/test/SemaObjC/psuedo-class-attribute.m b/test/SemaObjC/psuedo-class-attribute.m new file mode 100644 index 0000000000..c6ba077959 --- /dev/null +++ b/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; +} -- 2.40.0