forked from OSchip/llvm-project
[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 llvm-svn: 285391
This commit is contained in:
parent
3315a6a662
commit
a8c44ba2c0
|
@ -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>;
|
||||
|
|
|
@ -2667,3 +2667,11 @@ transparent union should have the same calling convention as its first member.
|
|||
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.
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -5776,6 +5776,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
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;
|
||||
|
|
|
@ -3853,6 +3853,18 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
|
|||
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, SourceRange AtEnd, ArrayRef<Decl *> allMethods,
|
|||
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.
|
||||
|
|
|
@ -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))
|
||||
@interface Leaf // okay
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface SubClassOfLeaf : Leaf // expected-note {{class is declared here}}
|
||||
@end
|
||||
|
||||
|
||||
@interface SubClass : SubClassOfLeaf // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
|
||||
@end
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface PlainRoot
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface Sub2Class : PlainRoot // okay
|
||||
@end
|
||||
|
||||
// rdar://28753587
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface SuperImplClass // expected-note {{class is declared here}}
|
||||
@end
|
||||
@implementation SuperImplClass
|
||||
@end
|
||||
|
||||
__attribute__((objc_subclassing_restricted))
|
||||
@interface SubImplClass : SuperImplClass
|
||||
@end
|
||||
@implementation SubImplClass // expected-error {{cannot subclass a class that was declared with the 'objc_subclassing_restricted' attribute}}
|
||||
@end
|
Loading…
Reference in New Issue