From 94724f979db1555a3daa2d801983bc7cc2f4ed17 Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Mon, 9 Jan 2023 00:26:32 -0800 Subject: [PATCH] [Sema] RuntimeMetadata: Make sure that inferred attributes have source information If an attribute is inferred from a protocol conformance it won't have any source information, in such cases let's determine where an attribute could have been inserted if it was spelled explicitly and use that location in a synthesized initializer call. Resolves: rdar://103938899 --- lib/Sema/TypeCheckRuntimeMetadataAttr.cpp | 17 +++-- .../SILGen/Inputs/runtime_metadata_defs.swift | 10 +++ test/SILGen/runtime_attributes.swift | 67 +++++++++++++++++++ 3 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 test/SILGen/Inputs/runtime_metadata_defs.swift create mode 100644 test/SILGen/runtime_attributes.swift diff --git a/lib/Sema/TypeCheckRuntimeMetadataAttr.cpp b/lib/Sema/TypeCheckRuntimeMetadataAttr.cpp index 73f78c6f207a7..dfce70f66af55 100644 --- a/lib/Sema/TypeCheckRuntimeMetadataAttr.cpp +++ b/lib/Sema/TypeCheckRuntimeMetadataAttr.cpp @@ -283,11 +283,16 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate( initArgument = keyPath; } - auto reprRange = SourceRange(); - if (auto *repr = attr->getTypeRepr()) - reprRange = repr->getSourceRange(); + SourceRange sourceRange; + if (auto *repr = attr->getTypeRepr()) { + sourceRange = repr->getSourceRange(); + } else { + sourceRange = SourceRange( + attachedTo->getAttributeInsertionLoc(/*forModifier=*/false)); + } - auto typeExpr = TypeExpr::createImplicitHack(reprRange.Start, attrType, ctx); + auto typeExpr = + TypeExpr::createImplicitHack(sourceRange.Start, attrType, ctx); // Add the initializer argument at the front of the argument list SmallVector newArgs; @@ -295,8 +300,8 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate( if (auto *attrArgs = attr->getArgs()) newArgs.append(attrArgs->begin(), attrArgs->end()); - ArgumentList *argList = ArgumentList::createImplicit(ctx, reprRange.Start, - newArgs, reprRange.End); + ArgumentList *argList = ArgumentList::createImplicit( + ctx, sourceRange.Start, newArgs, sourceRange.End); Expr *init = CallExpr::createImplicit(ctx, typeExpr, argList); // result of generator is an optional always. diff --git a/test/SILGen/Inputs/runtime_metadata_defs.swift b/test/SILGen/Inputs/runtime_metadata_defs.swift new file mode 100644 index 0000000000000..408d1c8afda9a --- /dev/null +++ b/test/SILGen/Inputs/runtime_metadata_defs.swift @@ -0,0 +1,10 @@ +@runtimeMetadata +public struct Ignore { + public init(attachedTo: T, + fileID: String = #fileID, + line: Int = #line, + column: Int = #column) {} +} + +@Ignore +public protocol Ignorable {} diff --git a/test/SILGen/runtime_attributes.swift b/test/SILGen/runtime_attributes.swift new file mode 100644 index 0000000000000..ae1a57adb876b --- /dev/null +++ b/test/SILGen/runtime_attributes.swift @@ -0,0 +1,67 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -enable-experimental-feature RuntimeDiscoverableAttrs -emit-module -o %t -enable-library-evolution %S/Inputs/runtime_metadata_defs.swift + +// This uses '-primary-file' to ensure we're conservative with lazy SIL emission. +// RUN: %target-swift-emit-silgen -enable-experimental-feature RuntimeDiscoverableAttrs -primary-file %s -I %t | %FileCheck %s + +// REQUIRES: asserts + +import runtime_metadata_defs + +/// Test that generator has source locations for both explicit and inferred attributes. + +// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes4TestAaBVmvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional +// CHECK: [[FILE_ID:%.*]] = string_literal utf8 "runtime_attributes/runtime_attributes.swift" +// CHECK: [[STRING_INIT:%.*]] = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC +// CHECK-NEXT: [[FILE_STR:%.*]] = apply [[STRING_INIT]]([[FILE_ID]], {{.*}}) +// CHECK: [[LINE_RAW:%.*]] = integer_literal $Builtin.IntLiteral, 25 +// CHECK: [[INT_INIT:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC +// CHECK-NEXT: [[LINE:%.*]] = apply [[INT_INIT]]([[LINE_RAW]], {{.*}}) +// CHECK: [[COLUMN_RAW:%.*]] = integer_literal $Builtin.IntLiteral, 1 +// CHECK: [[INT_INIT:%.*]] = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC +// CHECK-NEXT: [[COLUMN:%.*]] = apply [[INT_INIT]]([[COLUMN_RAW]], {{.*}}) +// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC +// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]({{.*}}, {{.*}}, [[FILE_STR]], [[LINE]], [[COLUMN]], {{.*}}) +struct Test : Ignorable {} + +// CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes8globalFnyycvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional +// CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift" +// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 33 +// CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 2 +// CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC +// CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<() -> ()>({{.*}}) +@Ignore func globalFn() {} + +struct MemberTests { + // CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV1xSivpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional + // CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift" + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 42 + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4 + // CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC + // CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]>({{.*}}) + @Ignore var x: Int = 42 + + // CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV6instFn_1xSSSi_SaySiGtcvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional + // CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift" + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 50 + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4 + // CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC + // CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(MemberTests, Int, [Int]) -> String>({{.*}}) + @Ignore func instFn(_: Int, x: [Int]) -> String { "" } + + // CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV8staticFn_1ySi_SStSS_SiztcvpZfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional + // CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift" + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 58 + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4 + // CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC + // CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(MemberTests.Type, String, inout Int) -> (Int, String)>({{.*}}) + @Ignore static func staticFn(_ x: String, y: inout Int) -> (Int, String) { (42, "") } + + // CHECK-LABEL: sil hidden [runtime_accessible] [ossa] @$s18runtime_attributes11MemberTestsV10mutatingFnSiycvpfa0A14_metadata_defs6Ignore : $@convention(thin) () -> @out Optional + // CHECK: {{.*}} = string_literal utf8 "runtime_attributes/runtime_attributes.swift" + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 66 + // CHECK: {{.*}} = integer_literal $Builtin.IntLiteral, 4 + // CHECK: [[IGNORE_INIT:%.*]] = function_ref @$s21runtime_metadata_defs6IgnoreV10attachedTo6fileID4line6columnACx_SSS2itclufC + // CHECK-NEXT: {{.*}} = apply [[IGNORE_INIT]]<(inout MemberTests) -> Int>({{.*}}) + @Ignore mutating func mutatingFn() -> Int { 42 } +}