summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2016-10-28 10:25:10 +0000
committerAlex Lorenz <arphaman@gmail.com>2016-10-28 10:25:10 +0000
commita8c44ba2c01e395ce478ae961ac9f8de1c37c149 (patch)
tree293ab8805019b760ec4b104f1aba243347e90ef3 /clang/lib/Sema
parent3315a6a662d20edef65355eb69102fd5baad5e78 (diff)
downloadbcm5719-llvm-a8c44ba2c01e395ce478ae961ac9f8de1c37c149.tar.gz
bcm5719-llvm-a8c44ba2c01e395ce478ae961ac9f8de1c37c149.zip
[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
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp20
2 files changed, 23 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 9413b6e51aa..936c29767d7 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -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;
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 79cdd6ead92..1b030801f23 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -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.
OpenPOWER on IntegriCloud