From 81b5d59363bb9a04c55c4992c60e6d1c82437467 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 25 Oct 2023 16:04:00 -0700 Subject: [PATCH 1/2] Diagnose root classes with @objcImpl @objcImpl, like @objc, cannot be used to implement root classes. Diagnose an attempt to do so. Fixes rdar://109130979. --- include/swift/AST/DiagnosticsSema.def | 4 ++++ lib/AST/Decl.cpp | 3 ++- lib/Sema/TypeCheckAttr.cpp | 7 +++++++ test/decl/ext/Inputs/objc_implementation.h | 4 ++++ test/decl/ext/objc_implementation.swift | 4 ++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index e81fe88fdeb90..2dc2bf72fb749 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1718,6 +1718,10 @@ ERROR(attr_objc_implementation_must_be_imported,none, "defined by a Swift 'class' declaration, not an imported Objective-C " "'@interface' declaration", (ValueDecl *)) +ERROR(attr_objc_implementation_must_have_super,none, + "'@_objcImplementation' cannot be used to implement root %kind0; declare " + "its superclass in the header", + (ValueDecl *)) ERROR(attr_objc_implementation_category_not_found,none, "could not find category %0 on Objective-C class %1; make sure your " "umbrella or bridging header imports the header that declares it", diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 009709eabbf9e..fcc506e7aefa1 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1825,7 +1825,8 @@ llvm::Optional ExtensionDecl::getCategoryNameForObjCImplementation() const { assert(isObjCImplementation()); - auto attr = getAttrs().getAttribute(); + auto attr = getAttrs() + .getAttribute(/*AllowInvalid=*/true); if (attr->isCategoryNameInvalid()) return llvm::None; diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 098513e9d0b09..3bc7f889e2ec5 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1503,6 +1503,13 @@ visitObjCImplementationAttr(ObjCImplementationAttr *attr) { return; } + if (!CD->hasSuperclass()) { + diagnoseAndRemoveAttr(attr, diag::attr_objc_implementation_must_have_super, + CD); + CD->diagnose(diag::decl_declared_here, CD); + return; + } + if (!attr->isCategoryNameInvalid() && !ED->getImplementedObjCDecl()) { diagnose(attr->getLocation(), diag::attr_objc_implementation_category_not_found, diff --git a/test/decl/ext/Inputs/objc_implementation.h b/test/decl/ext/Inputs/objc_implementation.h index cb8cab3f85db0..cfa12c3964e9e 100644 --- a/test/decl/ext/Inputs/objc_implementation.h +++ b/test/decl/ext/Inputs/objc_implementation.h @@ -168,6 +168,10 @@ @end +@interface ObjCImplRootClass + +@end + struct ObjCStruct { diff --git a/test/decl/ext/objc_implementation.swift b/test/decl/ext/objc_implementation.swift index 91843adbd805b..33a7c2e6528a9 100644 --- a/test/decl/ext/objc_implementation.swift +++ b/test/decl/ext/objc_implementation.swift @@ -456,6 +456,10 @@ protocol EmptySwiftProto {} @_objcImplementation(WTF) extension SwiftClass {} // expected // expected-error@-1 {{'@_objcImplementation' cannot be used to extend class 'SwiftClass' because it was defined by a Swift 'class' declaration, not an imported Objective-C '@interface' declaration}} {{1-27=}} +@_objcImplementation extension ObjCImplRootClass { + // expected-error@-1 {{'@_objcImplementation' cannot be used to implement root class 'ObjCImplRootClass'; declare its superclass in the header}} +} + func usesAreNotAmbiguous(obj: ObjCClass) { obj.method(fromHeader1: 1) obj.method(fromHeader2: 2) From 6b795a493ec82b0ff89168ae44f3dd2cb1f6e2e9 Mon Sep 17 00:00:00 2001 From: Becca Royal-Gordon Date: Wed, 25 Oct 2023 16:15:22 -0700 Subject: [PATCH 2/2] Diagnose lightweight generic classes with objcImpl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extensions to lightweight generic classes are such a huge mess that we’re just removing these from the feature’s scope for now. Fixes rdar://116066409. --- include/swift/AST/DiagnosticsSema.def | 3 +++ lib/Sema/TypeCheckAttr.cpp | 6 ++++++ test/decl/ext/Inputs/objc_implementation.h | 4 ++++ test/decl/ext/objc_implementation.swift | 4 ++++ 4 files changed, 17 insertions(+) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 2dc2bf72fb749..1dcd67267514d 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1722,6 +1722,9 @@ ERROR(attr_objc_implementation_must_have_super,none, "'@_objcImplementation' cannot be used to implement root %kind0; declare " "its superclass in the header", (ValueDecl *)) +ERROR(objc_implementation_cannot_have_generics,none, + "'@_objcImplementation' cannot be used to implement %kind0", + (ValueDecl *)) ERROR(attr_objc_implementation_category_not_found,none, "could not find category %0 on Objective-C class %1; make sure your " "umbrella or bridging header imports the header that declares it", diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 3bc7f889e2ec5..5acba237de7ca 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1510,6 +1510,12 @@ visitObjCImplementationAttr(ObjCImplementationAttr *attr) { return; } + if (CD->isTypeErasedGenericClass()) { + diagnoseAndRemoveAttr(attr, diag::objc_implementation_cannot_have_generics, + CD); + CD->diagnose(diag::decl_declared_here, CD); + } + if (!attr->isCategoryNameInvalid() && !ED->getImplementedObjCDecl()) { diagnose(attr->getLocation(), diag::attr_objc_implementation_category_not_found, diff --git a/test/decl/ext/Inputs/objc_implementation.h b/test/decl/ext/Inputs/objc_implementation.h index cfa12c3964e9e..acc194b4018cd 100644 --- a/test/decl/ext/Inputs/objc_implementation.h +++ b/test/decl/ext/Inputs/objc_implementation.h @@ -172,6 +172,10 @@ @end +@interface ObjCImplGenericClass : NSObject + +@end + struct ObjCStruct { diff --git a/test/decl/ext/objc_implementation.swift b/test/decl/ext/objc_implementation.swift index 33a7c2e6528a9..f1604642886e8 100644 --- a/test/decl/ext/objc_implementation.swift +++ b/test/decl/ext/objc_implementation.swift @@ -460,6 +460,10 @@ protocol EmptySwiftProto {} // expected-error@-1 {{'@_objcImplementation' cannot be used to implement root class 'ObjCImplRootClass'; declare its superclass in the header}} } +@_objcImplementation extension ObjCImplGenericClass { + // expected-error@-1 {{'@_objcImplementation' cannot be used to implement generic class 'ObjCImplGenericClass'}} +} + func usesAreNotAmbiguous(obj: ObjCClass) { obj.method(fromHeader1: 1) obj.method(fromHeader2: 2)