diff options
| author | Alex Lorenz <arphaman@gmail.com> | 2016-10-28 10:25:10 +0000 |
|---|---|---|
| committer | Alex Lorenz <arphaman@gmail.com> | 2016-10-28 10:25:10 +0000 |
| commit | a8c44ba2c01e395ce478ae961ac9f8de1c37c149 (patch) | |
| tree | 293ab8805019b760ec4b104f1aba243347e90ef3 /clang/lib/Sema | |
| parent | 3315a6a662d20edef65355eb69102fd5baad5e78 (diff) | |
| download | bcm5719-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.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 20 |
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. |

