diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index 6c5b2fbad3ca7..2003f7f929c3d 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -1057,7 +1057,8 @@ emitMemberInit(SILGenFunction &SGF, VarDecl *selfDecl, Pattern *pattern) { slot = SGF.B.createStructElementAddr(pattern, self.forward(SGF), field, fieldTy.getAddressType()); } else { - assert(isa(field->getDeclContext())); + assert(isa(field->getDeclContext()-> + getImplementedObjCContext())); slot = SGF.B.createRefElementAddr(pattern, self.forward(SGF), field, fieldTy.getAddressType()); } @@ -1154,7 +1155,7 @@ void SILGenFunction::emitMemberInitializers(DeclContext *dc, NominalTypeDecl *nominal) { auto subs = getSubstitutionsForPropertyInitializer(dc, nominal); - for (auto member : nominal->getMembers()) { + for (auto member : nominal->getImplementationContext()->getMembers()) { // Find instance pattern binding declarations that have initializers. if (auto pbd = dyn_cast(member)) { if (pbd->isStatic()) continue; diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 55bfc480795d8..77682668ec6cc 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -619,12 +619,26 @@ createDesignatedInitOverrideGenericParams(ASTContext &ctx, ArrayRef(), SourceLoc()); } +/// True if the type has an opaque clang implementation, meaning it is imported +/// and doesn't have an \c \@objcImplementation extension. +static bool hasClangImplementation(const NominalTypeDecl *decl) { + return decl->hasClangNode() && !decl->getObjCImplementationDecl(); +} + +/// True if \p member is in the main body of \p ty, where the "main body" is +/// either the type itself (the usual case) or its \c \@objcImplementation +/// extension (if one is present). +static bool isInMainBody(ValueDecl *member, NominalTypeDecl *ty) { + return member->getDeclContext() == + ty->getImplementationContext()->getAsGenericContext(); +} + static void configureInheritedDesignatedInitAttributes(ClassDecl *classDecl, ConstructorDecl *ctor, ConstructorDecl *superclassCtor, ASTContext &ctx) { - assert(ctor->getDeclContext() == classDecl); + assert(isInMainBody(ctor, classDecl)); AccessLevel access = classDecl->getFormalAccess(); access = std::max(access, AccessLevel::Internal); @@ -856,6 +870,7 @@ createDesignatedInitOverride(ClassDecl *classDecl, // Create the initializer declaration, inheriting the name, // failability, and throws from the superclass initializer. + auto implCtx = classDecl->getImplementationContext()->getAsGenericContext(); auto ctor = new (ctx) ConstructorDecl(superclassCtor->getName(), classDecl->getBraces().Start, @@ -865,8 +880,7 @@ createDesignatedInitOverride(ClassDecl *classDecl, /*AsyncLoc=*/SourceLoc(), /*Throws=*/superclassCtor->hasThrows(), /*ThrowsLoc=*/SourceLoc(), - bodyParams, genericParams, - classDecl); + bodyParams, genericParams, implCtx); ctor->setImplicit(); @@ -988,9 +1002,9 @@ static void diagnoseMissingRequiredInitializer( bool AreAllStoredPropertiesDefaultInitableRequest::evaluate( Evaluator &evaluator, NominalTypeDecl *decl) const { - assert(!decl->hasClangNode()); + assert(!hasClangImplementation(decl)); - for (auto member : decl->getMembers()) { + for (auto member : decl->getImplementationContext()->getMembers()) { // If a stored property lacks an initial value and if there is no way to // synthesize an initial value (e.g. for an optional) then we suppress // generation of the default initializer. @@ -1031,7 +1045,7 @@ bool AreAllStoredPropertiesDefaultInitableRequest::evaluate( static bool areAllStoredPropertiesDefaultInitializable(Evaluator &eval, NominalTypeDecl *decl) { - if (decl->hasClangNode()) + if (hasClangImplementation(decl)) return true; return evaluateOrDefault( @@ -1041,11 +1055,11 @@ static bool areAllStoredPropertiesDefaultInitializable(Evaluator &eval, bool HasUserDefinedDesignatedInitRequest::evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const { - assert(!decl->hasClangNode()); + assert(!hasClangImplementation(decl)); auto results = decl->lookupDirect(DeclBaseName::createConstructor()); for (auto *member : results) { - if (isa(member->getDeclContext())) + if (!isInMainBody(member, decl)) continue; auto *ctor = cast(member); @@ -1059,7 +1073,7 @@ HasUserDefinedDesignatedInitRequest::evaluate(Evaluator &evaluator, static bool hasUserDefinedDesignatedInit(Evaluator &eval, NominalTypeDecl *decl) { // Imported decls don't have a designated initializer defined by the user. - if (decl->hasClangNode()) + if (hasClangImplementation(decl)) return false; return evaluateOrDefault(eval, HasUserDefinedDesignatedInitRequest{decl}, @@ -1086,7 +1100,7 @@ static void collectNonOveriddenSuperclassInits( auto ctors = subclass->lookupDirect(DeclBaseName::createConstructor()); for (auto *member : ctors) { - if (isa(member->getDeclContext())) + if (!isInMainBody(member, subclass)) continue; auto *ctor = cast(member); @@ -1189,7 +1203,7 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) { auto results = decl->lookupDirect(DeclBaseName::createConstructor()); for (auto *member : results) { - if (isa(member->getDeclContext())) + if (!isInMainBody(member, decl)) continue; auto *ctor = cast(member); @@ -1217,7 +1231,7 @@ static void addImplicitInheritedConstructorsToClass(ClassDecl *decl) { if (auto ctor = createDesignatedInitOverride( decl, superclassCtor, kind, ctx)) { - decl->addMember(ctor); + decl->getImplementationContext()->addMember(ctor); } } } @@ -1258,7 +1272,7 @@ InheritsSuperclassInitializersRequest::evaluate(Evaluator &eval, static bool shouldAttemptInitializerSynthesis(const NominalTypeDecl *decl) { // Don't synthesize initializers for imported decls. - if (decl->hasClangNode()) + if (hasClangImplementation(decl)) return false; // Don't add implicit constructors in module interfaces. diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index ce59679490891..bfdea84e03ef3 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -2737,7 +2737,7 @@ static ArrayRef evaluateMembersRequest( return ctx.AllocateCopy(result); } - auto nominal = dyn_cast(idc); + auto nominal = dyn_cast(dc->getImplementedObjCContext()); if (nominal) { // We need to add implicit initializers because they diff --git a/test/IRGen/Inputs/objc_implementation.h b/test/IRGen/Inputs/objc_implementation.h index c131a3ab7271e..aff13897e623f 100644 --- a/test/IRGen/Inputs/objc_implementation.h +++ b/test/IRGen/Inputs/objc_implementation.h @@ -30,3 +30,12 @@ - (void)noImplMethod:(int)param; @end + +@interface NoInitImplClass: NSObject + +@property (readonly, strong, nonnull) NSString *s1; +@property (strong, nonnull) NSString *s2; +@property (readonly, strong, nonnull) NSString *s3; +@property (strong, nonnull) NSString *s4; + +@end diff --git a/test/IRGen/objc_implementation.swift b/test/IRGen/objc_implementation.swift index eaef86e6e590d..157ca04f97da8 100644 --- a/test/IRGen/objc_implementation.swift +++ b/test/IRGen/objc_implementation.swift @@ -1,4 +1,5 @@ -// REQUIRES: rdar101420862 +// Test doesn't pass on all platforms (rdar://101420862) +// REQUIRES: OS=macosx // RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/abi -F %clang-importer-sdk-path/frameworks %s -import-objc-header %S/Inputs/objc_implementation.h -emit-ir > %t.ir // RUN: %FileCheck --input-file %t.ir %s @@ -15,13 +16,12 @@ // CHECK: @"OBJC_METACLASS_$_ImplClass" = global %objc_class { %objc_class* @"OBJC_METACLASS_$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, {{i64 ptrtoint|%swift.opaque\* bitcast}} ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* [[_METACLASS_DATA_ImplClass:@[^, ]+]] to {{i64|%swift.opaque\*}}) }, align 8 // CHECK: [[_METACLASS_DATA_ImplClass]] = internal constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9.ImplClass, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 // TODO: Why the extra i32 field above? -// CHECK: [[selector_data_init:@[^, ]+]] = private global [5 x i8] c"init\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // Class // CHECK: [[selector_data_implProperty:@[^, ]+]] = private global [13 x i8] c"implProperty\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK: [[selector_data_setImplProperty_:@[^, ]+]] = private global [17 x i8] c"setImplProperty:\00", section "__TEXT,__objc_methname,cstring_literals", align 1 // CHECK: [[selector_data__cxx_destruct:@[^, ]+]] = private global [14 x i8] c".cxx_destruct\00", section "__TEXT,__objc_methname,cstring_literals", align 1 -// CHECK: [[_INSTANCE_METHODS_ImplClass:@[^, ]+]] = internal constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[selector_data_init]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationEABycfcTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([13 x i8], [13 x i8]* [[selector_data_implProperty]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.i16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE12implPropertys5Int32VvgTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[selector_data_setImplProperty_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE12implPropertys5Int32VvsTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[selector_data_mainMethod_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE10mainMethodyys5Int32VFTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[selector_data__cxx_destruct]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.v16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassCfETo{{(\.ptrauth)?}}" to i8*) }] }, section "__DATA, __objc_data", align 8 +// CHECK: [[_INSTANCE_METHODS_ImplClass:@[^, ]+]] = internal constant { i32, i32, [5 x { i8*, i8*, i8* }] } { i32 24, i32 5, [5 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationEABycfcTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([13 x i8], [13 x i8]* [[selector_data_implProperty]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.i16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE12implPropertys5Int32VvgTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([17 x i8], [17 x i8]* [[selector_data_setImplProperty_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE12implPropertys5Int32VvsTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[selector_data_mainMethod_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassC19objc_implementationE10mainMethodyys5Int32VFTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8], [14 x i8]* [[selector_data__cxx_destruct]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.v16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$sSo9ImplClassCfETo{{(\.ptrauth)?}}" to i8*) }] }, section "__DATA, __objc_data", align 8 // CHECK: [[_IVARS_ImplClass:@[^, ]+]] = internal constant { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 2, [2 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @"$sSo9ImplClassC19objc_implementationE12implPropertys5Int32VvpWvd", i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.12.implProperty, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 2, i32 4 }, { i64*, i8*, i8*, i32, i32 } { i64* @"$sSo9ImplClassC19objc_implementationE13implProperty2So8NSObjectCSgvpWvd", i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str.13.implProperty2, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 3, i32 8 }] }, section "__DATA, __objc_const", align 8 // CHECK: [[_PROPERTIES_ImplClass:@[^, ]+]] = internal constant { i32, i32, [1 x { i8*, i8* }] } { i32 16, i32 1, [1 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.12.implProperty, i64 0, i64 0), i8* getelementptr inbounds ([19 x i8], [19 x i8]* @".str.18.Ti,N,VimplProperty", i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 // CHECK: [[_DATA_ImplClass:@[^, ]+]] = internal constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [5 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [1 x { i8*, i8* }] }* } { i32 388, i32 8, i32 24, i32 0, i8* null, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.9.ImplClass, i64 0, i64 0), { i32, i32, [5 x { i8*, i8*, i8* }] }* [[_INSTANCE_METHODS_ImplClass]], i8* null, { i32, i32, [2 x { i64*, i8*, i8*, i32, i32 }] }* [[_IVARS_ImplClass]], i8* null, { i32, i32, [1 x { i8*, i8* }] }* [[_PROPERTIES_ImplClass]] }, section "__DATA, __objc_data", align 8 @@ -66,6 +66,24 @@ } } +// +// Second @_objcImplementation class, inherited initializer +// + +// CHECK: @"OBJC_METACLASS_$_NoInitImplClass" = global %objc_class { %objc_class* @"OBJC_METACLASS_$_NSObject", %objc_class* @"OBJC_METACLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @_METACLASS_DATA_NoInitImplClass to i64) }, align 8 +// CHECK: @_METACLASS_DATA_NoInitImplClass = internal constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.15.NoInitImplClass, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 +// CHECK: @_INSTANCE_METHODS_NoInitImplClass = internal constant { i32, i32, [8 x { i8*, i8*, i8* }] } { i32 24, i32 8, [8 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_selector_data(s1)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast (%2* (%3*, i8*)* @"$sSo15NoInitImplClassC19objc_implementationE2s1SSvgTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_selector_data(s2)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast (%2* (%3*, i8*)* @"$sSo15NoInitImplClassC19objc_implementationE2s2SSvgTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_selector_data(setS2:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v24@0:8@16", i64 0, i64 0), i8* bitcast (void (%3*, i8*, %2*)* @"$sSo15NoInitImplClassC19objc_implementationE2s2SSvsTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_selector_data(s3)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast (%2* (%3*, i8*)* @"$sSo15NoInitImplClassC19objc_implementationE2s3SSvgTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @"\01L_selector_data(s4)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast (%2* (%3*, i8*)* @"$sSo15NoInitImplClassC19objc_implementationE2s4SSvgTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"\01L_selector_data(setS4:)", i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v24@0:8@16", i64 0, i64 0), i8* bitcast (void (%3*, i8*, %2*)* @"$sSo15NoInitImplClassC19objc_implementationE2s4SSvsTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast (%3* (%3*, i8*)* @"$sSo15NoInitImplClassC19objc_implementationEABycfcTo" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"\01L_selector_data(.cxx_destruct)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.v16@0:8", i64 0, i64 0), i8* bitcast (void (%3*, i8*)* @"$sSo15NoInitImplClassCfETo" to i8*) }] }, section "__DATA, __objc_data", align 8 +// CHECK: @_IVARS_NoInitImplClass = internal constant { i32, i32, [4 x { i64*, i8*, i8*, i32, i32 }] } { i32 32, i32 4, [4 x { i64*, i8*, i8*, i32, i32 }] [{ i64*, i8*, i8*, i32, i32 } { i64* @"$sSo15NoInitImplClassC19objc_implementationE2s1SSvpWvd", i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s1, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 3, i32 16 }, { i64*, i8*, i8*, i32, i32 } { i64* @"$sSo15NoInitImplClassC19objc_implementationE2s2SSvpWvd", i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s2, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 3, i32 16 }, { i64*, i8*, i8*, i32, i32 } { i64* @"$sSo15NoInitImplClassC19objc_implementationE2s3SSvpWvd", i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s3, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 3, i32 16 }, { i64*, i8*, i8*, i32, i32 } { i64* @"$sSo15NoInitImplClassC19objc_implementationE2s4SSvpWvd", i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s4, i64 0, i64 0), i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.0., i64 0, i64 0), i32 3, i32 16 }] }, section "__DATA, __objc_const", align 8 +// CHECK: @_PROPERTIES_NoInitImplClass = internal constant { i32, i32, [4 x { i8*, i8* }] } { i32 16, i32 4, [4 x { i8*, i8* }] [{ i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s1, i64 0, i64 0), i8* getelementptr inbounds ([17 x i8], [17 x i8]* @".str.16.T@\22NSString\22,N,R", i64 0, i64 0) }, { i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s2, i64 0, i64 0), i8* getelementptr inbounds ([17 x i8], [17 x i8]* @".str.16.T@\22NSString\22,N,C", i64 0, i64 0) }, { i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s3, i64 0, i64 0), i8* getelementptr inbounds ([17 x i8], [17 x i8]* @".str.16.T@\22NSString\22,N,R", i64 0, i64 0) }, { i8*, i8* } { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2.s4, i64 0, i64 0), i8* getelementptr inbounds ([17 x i8], [17 x i8]* @".str.16.T@\22NSString\22,N,C", i64 0, i64 0) }] }, section "__DATA, __objc_const", align 8 +// CHECK: @_DATA_NoInitImplClass = internal constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [8 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [4 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [4 x { i8*, i8* }] }* } { i32 388, i32 8, i32 72, i32 0, i8* null, i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str.15.NoInitImplClass, i64 0, i64 0), { i32, i32, [8 x { i8*, i8*, i8* }] }* @_INSTANCE_METHODS_NoInitImplClass, i8* null, { i32, i32, [4 x { i64*, i8*, i8*, i32, i32 }] }* @_IVARS_NoInitImplClass, i8* null, { i32, i32, [4 x { i8*, i8* }] }* @_PROPERTIES_NoInitImplClass }, section "__DATA, __objc_data", align 8 +// CHECK: @"OBJC_CLASS_$_NoInitImplClass" = global <{ i64, %objc_class*, %swift.opaque*, %swift.opaque*, { i32, i32, i32, i32, i8*, i8*, { i32, i32, [8 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [4 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [4 x { i8*, i8* }] }* }* }> <{ i64 ptrtoint (%objc_class* @"OBJC_METACLASS_$_NoInitImplClass" to i64), %objc_class* @"OBJC_CLASS_$_NSObject", %swift.opaque* @_objc_empty_cache, %swift.opaque* null, { i32, i32, i32, i32, i8*, i8*, { i32, i32, [8 x { i8*, i8*, i8* }] }*, i8*, { i32, i32, [4 x { i64*, i8*, i8*, i32, i32 }] }*, i8*, { i32, i32, [4 x { i8*, i8* }] }* }* @_DATA_NoInitImplClass }>, section "__DATA,__objc_data, regular", align 8 +@_objcImplementation extension NoInitImplClass { + @objc let s1 = "s1v" + @objc var s2 = "s2v" + @objc(s3) let s3 = "s3v" + @objc(s4) var s4 = "s4v" +} + // // @objc subclass of @_objcImplementation class // @@ -75,7 +93,7 @@ // CHECK: [[_METACLASS_DATA_SwiftSubclass]] = internal constant { i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* } { i32 129, i32 40, i32 40, i32 0, i8* null, i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.40._TtC19objc_implementation13SwiftSubclass, i64 0, i64 0), i8* null, i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_const", align 8 // Class -// CHECK: [[_INSTANCE_METHODS_SwiftSubclass:@[^, ]+]] = internal constant { i32, i32, [2 x { i8*, i8*, i8* }] } { i32 24, i32 2, [2 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[selector_data_mainMethod_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$s19objc_implementation13SwiftSubclassC10mainMethodyys5Int32VFTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8], [5 x i8]* [[selector_data_init]], i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$s19objc_implementation13SwiftSubclassCACycfcTo{{(\.ptrauth)?}}" to i8*) }] }, section "__DATA, __objc_data", align 8 +// CHECK: [[_INSTANCE_METHODS_SwiftSubclass:@[^, ]+]] = internal constant { i32, i32, [2 x { i8*, i8*, i8* }] } { i32 24, i32 2, [2 x { i8*, i8*, i8* }] [{ i8*, i8*, i8* } { i8* getelementptr inbounds ([12 x i8], [12 x i8]* [[selector_data_mainMethod_]], i64 0, i64 0), i8* getelementptr inbounds ([11 x i8], [11 x i8]* @".str.10.v20@0:8i16", i64 0, i64 0), i8* bitcast ({{.*}}* @"$s19objc_implementation13SwiftSubclassC10mainMethodyys5Int32VFTo{{(\.ptrauth)?}}" to i8*) }, { i8*, i8*, i8* } { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @"\01L_selector_data(init)", i64 0, i64 0), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @".str.7.@16@0:8", i64 0, i64 0), i8* bitcast ({{.*}}* @"$s19objc_implementation13SwiftSubclassCACycfcTo{{(\.ptrauth)?}}" to i8*) }] }, section "__DATA, __objc_data", align 8 // CHECK: [[_DATA_SwiftSubclass:@[^, ]+]] = internal constant { i32, i32, i32, i32, i8*, i8*, { i32, i32, [2 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, i8* } { i32 128, i32 24, i32 24, i32 0, i8* null, i8* getelementptr inbounds ([41 x i8], [41 x i8]* @.str.40._TtC19objc_implementation13SwiftSubclass, i64 0, i64 0), { i32, i32, [2 x { i8*, i8*, i8* }] }* [[_INSTANCE_METHODS_SwiftSubclass]], i8* null, i8* null, i8* null, i8* null }, section "__DATA, __objc_data", align 8 // Swift metadata @@ -172,6 +190,18 @@ public func fn(impl: ImplClass, swiftSub: SwiftSubclass) { // ObjC calling convention -[ImplClass(Category1) category1Method:] // CHECK-LABEL: define internal void @"$sSo9ImplClassC19objc_implementationE15category1Methodyys5Int32VFTo" +// Swift calling convention -[NoInitImplClass init] +// CHECK-LABEL: define swiftcc %TSo15NoInitImplClassC* @"$sSo15NoInitImplClassC19objc_implementationEABycfc" + // CHECK-DAG: load i64, i64* @"$sSo15NoInitImplClassC19objc_implementationE2s1SSvpWvd", align 8 + // CHECK-DAG: load i64, i64* @"$sSo15NoInitImplClassC19objc_implementationE2s2SSvpWvd", align 8 + // CHECK-DAG: load i64, i64* @"$sSo15NoInitImplClassC19objc_implementationE2s3SSvpWvd", align 8 + // CHECK-DAG: load i64, i64* @"$sSo15NoInitImplClassC19objc_implementationE2s4SSvpWvd", align 8 + // CHECK: [[SEL_init:%[^ ]+]] = load i8*, i8** @"\01L_selector(init)", align 8 + // CHECK: call %0* bitcast (void ()* @objc_msgSendSuper{{.*}} [[SEL_init]]) + +// ObjC calling convention -[NoInitImplClass init] +// CHECK-LABEL: define internal %3* @"$sSo15NoInitImplClassC19objc_implementationEABycfcTo" + // Swift calling convention SwiftSubclass.mainMethod(_:) // CHECK-LABEL: define swiftcc void @"$s19objc_implementation13SwiftSubclassC10mainMethodyys5Int32VF" @@ -187,8 +217,8 @@ public func fn(impl: ImplClass, swiftSub: SwiftSubclass) { // CHECK: [[PARAM_impl:%[^ ]+]] = bitcast %TSo9ImplClassC* %0 to %1* // CHECK: call void bitcast (void ()* @objc_msgSend to void (%1*, i8*, i32)*)(%1* [[PARAM_impl]], i8* [[SEL_1]], i32 0) // CHECK: [[SEL_2:%[^ ]+]] = load i8*, i8** @"\01L_selector(mainMethod:)", align 8 -// CHECK: [[PARAM_swiftSub:%[^ ]+]] = bitcast %T19objc_implementation13SwiftSubclassC* %1 to %2* -// CHECK: call void bitcast (void ()* @objc_msgSend to void (%2*, i8*, i32)*)(%2* [[PARAM_swiftSub]], i8* [[SEL_2]], i32 1) +// CHECK: [[PARAM_swiftSub:%[^ ]+]] = bitcast %T19objc_implementation13SwiftSubclassC* %1 to [[SEL_1]]* +// CHECK: call void bitcast (void ()* @objc_msgSend to void ([[SEL_1]]*, i8*, i32)*)([[SEL_1]]* [[PARAM_swiftSub]], i8* [[SEL_2]], i32 1) // CHECK: ret void // CHECK: } diff --git a/test/Interpreter/objc_implementation_swift_client.swift b/test/Interpreter/objc_implementation_swift_client.swift index 962497452bc9f..89cc0d2f7498e 100644 --- a/test/Interpreter/objc_implementation_swift_client.swift +++ b/test/Interpreter/objc_implementation_swift_client.swift @@ -1,4 +1,5 @@ -// REQUIRES: rdar101543397 +// Test doesn't pass on all platforms (rdar://101543397) +// REQUIRES: OS=macosx // // Build objc_implementation.framework