r285391 - [Objective-C] Add objc_subclassing_restricted attribute
Alex Lorenz via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 28 03:25:10 PDT 2016
Author: arphaman
Date: Fri Oct 28 05:25:10 2016
New Revision: 285391
URL: http://llvm.org/viewvc/llvm-project?rev=285391&view=rev
Log:
[Objective-C] Add objc_subclassing_restricted attribute
This patch adds an objc_subclassing_restricted attribute into clang. This
attribute acts similarly to 'final' - Objective-C classes with this attribute
can't be subclassed. However, @interface declarations that have
objc_subclassing_restricted but don't have @implementation are allowed to
inherit other @interface declarations with objc_subclassing_restricted. This is
needed to describe the Swift class hierarchy in clang while making sure that
the Objective-C classes cannot subclass the Swift classes.
This attribute is already implemented in a fork of clang that's used for Swift
(https://github.com/apple/swift-clang) and this patch moves that code to the
upstream clang repository.
rdar://28937548
Differential Revision: https://reviews.llvm.org/D25993
Added:
cfe/trunk/test/SemaObjC/subclassing-restricted-attr.m
Modified:
cfe/trunk/include/clang/Basic/Attr.td
cfe/trunk/include/clang/Basic/AttrDocs.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaDeclObjC.cpp
Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=285391&r1=285390&r2=285391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Oct 28 05:25:10 2016
@@ -1285,6 +1285,12 @@ def ObjCRootClass : InheritableAttr {
let Documentation = [Undocumented];
}
+def ObjCSubclassingRestricted : InheritableAttr {
+ let Spellings = [GNU<"objc_subclassing_restricted">];
+ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
+ let Documentation = [ObjCSubclassingRestrictedDocs];
+}
+
def ObjCExplicitProtocolImpl : InheritableAttr {
let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">];
let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=285391&r1=285390&r2=285391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Fri Oct 28 05:25:10 2016
@@ -2667,3 +2667,11 @@ transparent union should have the same c
Transparent unions are not supported in C++.
}];
}
+
+def ObjCSubclassingRestrictedDocs : Documentation {
+ let Category = DocCatType;
+ let Content = [{
+This attribute can be added to an Objective-C ``@interface`` declaration to
+ensure that this class cannot be subclassed.
+ }];
+}
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=285391&r1=285390&r2=285391&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 28 05:25:10 2016
@@ -781,6 +781,9 @@ def note_suppressed_class_declare : Note
"class with specified objc_requires_property_definitions attribute is declared here">;
def err_objc_root_class_subclass : Error<
"objc_root_class attribute may only be specified on a root class declaration">;
+def err_restricted_superclass_mismatch : Error<
+ "cannot subclass a class that was declared with the "
+ "'objc_subclassing_restricted' attribute">;
def warn_objc_root_class_missing : Warning<
"class %0 defined without specifying a base class">,
InGroup<ObjCRootClass>;
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=285391&r1=285390&r2=285391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Oct 28 05:25:10 2016
@@ -5776,6 +5776,9 @@ static void ProcessDeclAttribute(Sema &S
case AttributeList::AT_ObjCRootClass:
handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr);
break;
+ case AttributeList::AT_ObjCSubclassingRestricted:
+ handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, Attr);
+ break;
case AttributeList::AT_ObjCExplicitProtocolImpl:
handleObjCSuppresProtocolAttr(S, D, Attr);
break;
Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=285391&r1=285390&r2=285391&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Oct 28 05:25:10 2016
@@ -3853,6 +3853,18 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceR
Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);
}
+ if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) {
+ // An interface can subclass another interface with a
+ // objc_subclassing_restricted attribute when it has that attribute as
+ // well (because of interfaces imported from Swift). Therefore we have
+ // to check if we can subclass in the implementation as well.
+ if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
+ Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
+ Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch);
+ Diag(Super->getLocation(), diag::note_class_declared);
+ }
+ }
+
if (LangOpts.ObjCRuntime.isNonFragile()) {
while (IDecl->getSuperClass()) {
DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
@@ -3873,6 +3885,14 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceR
ImplMethodsVsClassMethods(S, CatImplClass, Cat);
}
}
+ } else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
+ if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) {
+ if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
+ Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
+ Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch);
+ Diag(Super->getLocation(), diag::note_class_declared);
+ }
+ }
}
if (isInterfaceDeclKind) {
// Reject invalid vardecls.
Added: cfe/trunk/test/SemaObjC/subclassing-restricted-attr.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/subclassing-restricted-attr.m?rev=285391&view=auto
==============================================================================
--- cfe/trunk/test/SemaObjC/subclassing-restricted-attr.m (added)
+++ cfe/trunk/test/SemaObjC/subclassing-restricted-attr.m Fri Oct 28 05:25:10 2016
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -x objective-c++ -fsyntax-only -verify -Wno-objc-root-class %s
+// rdar://16560476
+
+__attribute__((objc_subclassing_restricted))
+ at interface Leaf // okay
+ at end
+
+__attribute__((objc_subclassing_restricted))
+ at interface SubClassOfLeaf : Leaf // expected-note {{class is declared here}}
+ at end
+
+
+ at interface SubClass : SubClassOfLeaf // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
+ at end
+
+__attribute__((objc_root_class))
+ at interface PlainRoot
+ at end
+
+__attribute__((objc_subclassing_restricted))
+ at interface Sub2Class : PlainRoot // okay
+ at end
+
+// rdar://28753587
+__attribute__((objc_subclassing_restricted))
+ at interface SuperImplClass // expected-note {{class is declared here}}
+ at end
+ at implementation SuperImplClass
+ at end
+
+__attribute__((objc_subclassing_restricted))
+ at interface SubImplClass : SuperImplClass
+ at end
+ at implementation SubImplClass // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
+ at end
More information about the cfe-commits
mailing list