diff --git a/toolchain/check/testdata/class/syntactic_merge.carbon b/toolchain/check/testdata/class/syntactic_merge.carbon index f7469c8e686e..29d8fc5f6b16 100644 --- a/toolchain/check/testdata/class/syntactic_merge.carbon +++ b/toolchain/check/testdata/class/syntactic_merge.carbon @@ -50,13 +50,20 @@ class Foo(a:! C); // CHECK:STDERR: class Foo(a:! (C)) {} -// --- todo_fail_raw_identifier.carbon +// --- fail_raw_identifier.carbon library "[[@TEST_NAME]]"; class C {} class Foo(a:! C); +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE+7]]:15: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers] +// CHECK:STDERR: class Foo(a:! r#C) {} +// CHECK:STDERR: ^~~ +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE-4]]:15: note: comparing with previous declaration here [RedeclParamSyntaxPrevious] +// CHECK:STDERR: class Foo(a:! C); +// CHECK:STDERR: ^ +// CHECK:STDERR: class Foo(a:! r#C) {} // --- two_file.carbon @@ -440,7 +447,7 @@ fn Base.F[ref self: Base]() { // CHECK:STDOUT: %a.loc14_12.1 => constants.%a // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: --- fail_raw_identifier.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [concrete] @@ -450,9 +457,11 @@ fn Base.F[ref self: Base]() { // CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self] // CHECK:STDOUT: %pattern_type: type = pattern_type %C [concrete] // CHECK:STDOUT: %a: %C = symbolic_binding a, 0 [symbolic] -// CHECK:STDOUT: %Foo.type: type = generic_class_type @Foo [concrete] -// CHECK:STDOUT: %Foo.generic: %Foo.type = struct_value () [concrete] -// CHECK:STDOUT: %Foo: type = class_type @Foo, @Foo(%a) [symbolic] +// CHECK:STDOUT: %Foo.type.ca2247.1: type = generic_class_type @Foo.loc6 [concrete] +// CHECK:STDOUT: %Foo.generic.ac6dbc.1: %Foo.type.ca2247.1 = struct_value () [concrete] +// CHECK:STDOUT: %Foo.type.ca2247.2: type = generic_class_type @Foo.loc14 [concrete] +// CHECK:STDOUT: %Foo.generic.ac6dbc.2: %Foo.type.ca2247.2 = struct_value () [concrete] +// CHECK:STDOUT: %Foo.877b4b.2: type = class_type @Foo.loc14, @Foo.loc14(%a) [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -461,23 +470,23 @@ fn Base.F[ref self: Base]() { // CHECK:STDOUT: .Foo = %Foo.decl.loc6 // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] { +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type.ca2247.1 = class_decl @Foo.loc6 [concrete = constants.%Foo.generic.ac6dbc.1] { // CHECK:STDOUT: %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc6: type = splice_block %C.ref.loc6 [concrete = constants.%C] { -// CHECK:STDOUT: %.Self.loc6: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %.loc6: type = splice_block %C.ref [concrete = constants.%C] { +// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: %a.loc6_12.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_12.1 (constants.%a)] // CHECK:STDOUT: } -// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = class_decl @Foo [concrete = constants.%Foo.generic] { +// CHECK:STDOUT: %Foo.decl.loc14: %Foo.type.ca2247.2 = class_decl @Foo.loc14 [concrete = constants.%Foo.generic.ac6dbc.2] { // CHECK:STDOUT: %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc7: type = splice_block %C.ref.loc7 [concrete = constants.%C] { -// CHECK:STDOUT: %.Self.loc7: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %.loc14: type = splice_block %C.ref [concrete = constants.%C] { +// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } -// CHECK:STDOUT: %a.loc7: %C = symbolic_binding a, 0 [symbolic = %a.loc6_12.1 (constants.%a)] +// CHECK:STDOUT: %a.loc14_12.2: %C = symbolic_binding a, 0 [symbolic = %a.loc14_12.1 (constants.%a)] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -489,9 +498,15 @@ fn Base.F[ref self: Base]() { // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic class @Foo(%a.loc6_12.2: %C) { +// CHECK:STDOUT: generic class @Foo.loc6(%a.loc6_12.2: %C) { // CHECK:STDOUT: %a.loc6_12.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_12.1 (constants.%a)] // CHECK:STDOUT: +// CHECK:STDOUT: class; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic class @Foo.loc14(%a.loc14_12.2: %C) { +// CHECK:STDOUT: %a.loc14_12.1: %C = symbolic_binding a, 0 [symbolic = %a.loc14_12.1 (constants.%a)] +// CHECK:STDOUT: // CHECK:STDOUT: !definition: // CHECK:STDOUT: // CHECK:STDOUT: class { @@ -499,14 +514,18 @@ fn Base.F[ref self: Base]() { // CHECK:STDOUT: complete_type_witness = %complete_type // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%Foo +// CHECK:STDOUT: .Self = constants.%Foo.877b4b.2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @Foo(constants.%a) { +// CHECK:STDOUT: specific @Foo.loc6(constants.%a) { // CHECK:STDOUT: %a.loc6_12.1 => constants.%a // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Foo.loc14(constants.%a) { +// CHECK:STDOUT: %a.loc14_12.1 => constants.%a +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: --- two_file.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { diff --git a/toolchain/check/testdata/function/definition/syntactic_merge.carbon b/toolchain/check/testdata/function/definition/syntactic_merge.carbon index 8f986a2bcdbd..134c403a870a 100644 --- a/toolchain/check/testdata/function/definition/syntactic_merge.carbon +++ b/toolchain/check/testdata/function/definition/syntactic_merge.carbon @@ -75,14 +75,21 @@ fn Foo[a: C]; // CHECK:STDERR: fn Foo[a: (C)] {} -// --- todo_fail_raw_identifier.carbon +// --- fail_raw_identifier.carbon library "[[@TEST_NAME]]"; class C {} -fn Foo(a: C); -fn Foo(unused a: r#C) {} +fn Foo(_: C); +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE+7]]:11: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers] +// CHECK:STDERR: fn Foo(_: r#C) {} +// CHECK:STDERR: ^~~ +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE-4]]:11: note: comparing with previous declaration here [RedeclParamSyntaxPrevious] +// CHECK:STDERR: fn Foo(_: C); +// CHECK:STDERR: ^ +// CHECK:STDERR: +fn Foo(_: r#C) {} // --- two_file.carbon @@ -410,15 +417,17 @@ fn Foo(unused a: const (const C)) {} // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: --- fail_raw_identifier.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [concrete] // CHECK:STDOUT: %empty_struct_type: type = struct_type {} [concrete] // CHECK:STDOUT: %complete_type: = complete_type_witness %empty_struct_type [concrete] // CHECK:STDOUT: %pattern_type: type = pattern_type %C [concrete] -// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [concrete] -// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [concrete] +// CHECK:STDOUT: %Foo.type.2d3852.1: type = fn_type @Foo.loc6 [concrete] +// CHECK:STDOUT: %Foo.371266.1: %Foo.type.2d3852.1 = struct_value () [concrete] +// CHECK:STDOUT: %Foo.type.2d3852.2: type = fn_type @Foo.loc14 [concrete] +// CHECK:STDOUT: %Foo.371266.2: %Foo.type.2d3852.2 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: file { @@ -427,21 +436,21 @@ fn Foo(unused a: const (const C)) {} // CHECK:STDOUT: .Foo = %Foo.decl.loc6 // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] { -// CHECK:STDOUT: %a.param_patt: %pattern_type = value_param_pattern [concrete] -// CHECK:STDOUT: %a.patt: %pattern_type = at_binding_pattern a, %a.param_patt [concrete] +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type.2d3852.1 = fn_decl @Foo.loc6 [concrete = constants.%Foo.371266.1] { +// CHECK:STDOUT: %_.param_patt: %pattern_type = value_param_pattern [concrete] +// CHECK:STDOUT: %_.patt: %pattern_type = at_binding_pattern _, %_.param_patt [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %a.param.loc6: %C = value_param call_param0 -// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %a.loc6: %C = value_binding a, %a.param.loc6 +// CHECK:STDOUT: %_.param: %C = value_param call_param0 +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %_: %C = value_binding _, %_.param // CHECK:STDOUT: } -// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type = fn_decl @Foo [concrete = constants.%Foo] { -// CHECK:STDOUT: %a.param_patt: %pattern_type = value_param_pattern [concrete] -// CHECK:STDOUT: %a.patt: %pattern_type = at_binding_pattern a, %a.param_patt [concrete] +// CHECK:STDOUT: %Foo.decl.loc14: %Foo.type.2d3852.2 = fn_decl @Foo.loc14 [concrete = constants.%Foo.371266.2] { +// CHECK:STDOUT: %_.param_patt: %pattern_type = value_param_pattern [concrete] +// CHECK:STDOUT: %_.patt: %pattern_type = at_binding_pattern _, %_.param_patt [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %a.param.loc7: %C = value_param call_param0 -// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C] -// CHECK:STDOUT: %a.loc7: %C = value_binding a, %a.param.loc7 +// CHECK:STDOUT: %_.param: %C = value_param call_param0 +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %_: %C = value_binding _, %_.param // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: @@ -453,7 +462,9 @@ fn Foo(unused a: const (const C)) {} // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @Foo(%a.param.loc7: %C) { +// CHECK:STDOUT: fn @Foo.loc6(%_.param: %C); +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo.loc14(%_.param: %C) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/interface/syntactic_merge.carbon b/toolchain/check/testdata/interface/syntactic_merge.carbon index 170f0fc1ed5b..516b76224b77 100644 --- a/toolchain/check/testdata/interface/syntactic_merge.carbon +++ b/toolchain/check/testdata/interface/syntactic_merge.carbon @@ -50,13 +50,20 @@ interface Foo(a:! C); // CHECK:STDERR: interface Foo(a:! (C)) {} -// --- todo_fail_raw_identifier.carbon +// --- fail_raw_identifier.carbon library "[[@TEST_NAME]]"; class C {} interface Foo(a:! C); +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE+7]]:19: error: redeclaration syntax differs here [RedeclParamSyntaxDiffers] +// CHECK:STDERR: interface Foo(a:! r#C) {} +// CHECK:STDERR: ^~~ +// CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE-4]]:19: note: comparing with previous declaration here [RedeclParamSyntaxPrevious] +// CHECK:STDERR: interface Foo(a:! C); +// CHECK:STDERR: ^ +// CHECK:STDERR: interface Foo(a:! r#C) {} // --- two_file.carbon @@ -478,7 +485,7 @@ interface Foo(a:! const (const C)) {} // CHECK:STDOUT: // CHECK:STDOUT: specific @Foo.WithSelf(constants.%a, constants.%Self) {} // CHECK:STDOUT: -// CHECK:STDOUT: --- todo_fail_raw_identifier.carbon +// CHECK:STDOUT: --- fail_raw_identifier.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %C: type = class_type @C [concrete] @@ -488,9 +495,11 @@ interface Foo(a:! const (const C)) {} // CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self] // CHECK:STDOUT: %pattern_type: type = pattern_type %C [concrete] // CHECK:STDOUT: %a: %C = symbolic_binding a, 0 [symbolic] -// CHECK:STDOUT: %Foo.type.09e: type = generic_interface_type @Foo [concrete] -// CHECK:STDOUT: %Foo.generic: %Foo.type.09e = struct_value () [concrete] -// CHECK:STDOUT: %Foo.type.01e: type = facet_type <@Foo, @Foo(%a)> [symbolic] +// CHECK:STDOUT: %Foo.type.09efb5.1: type = generic_interface_type @Foo.loc6 [concrete] +// CHECK:STDOUT: %Foo.generic.dc5ede.1: %Foo.type.09efb5.1 = struct_value () [concrete] +// CHECK:STDOUT: %Foo.type.09efb5.2: type = generic_interface_type @Foo.loc14 [concrete] +// CHECK:STDOUT: %Foo.generic.dc5ede.2: %Foo.type.09efb5.2 = struct_value () [concrete] +// CHECK:STDOUT: %Foo.type.01e: type = facet_type <@Foo.loc14, @Foo.loc14(%a)> [symbolic] // CHECK:STDOUT: %Self: %Foo.type.01e = symbolic_binding Self, 1 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -500,39 +509,45 @@ interface Foo(a:! const (const C)) {} // CHECK:STDOUT: .Foo = %Foo.decl.loc6 // CHECK:STDOUT: } // CHECK:STDOUT: %C.decl: type = class_decl @C [concrete = constants.%C] {} {} -// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type.09e = interface_decl @Foo [concrete = constants.%Foo.generic] { +// CHECK:STDOUT: %Foo.decl.loc6: %Foo.type.09efb5.1 = interface_decl @Foo.loc6 [concrete = constants.%Foo.generic.dc5ede.1] { // CHECK:STDOUT: %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc6: type = splice_block %C.ref.loc6 [concrete = constants.%C] { -// CHECK:STDOUT: %.Self.loc6: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %C.ref.loc6: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %.loc6: type = splice_block %C.ref [concrete = constants.%C] { +// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } // CHECK:STDOUT: %a.loc6_16.2: %C = symbolic_binding a, 0 [symbolic = %a.loc6_16.1 (constants.%a)] // CHECK:STDOUT: } -// CHECK:STDOUT: %Foo.decl.loc7: %Foo.type.09e = interface_decl @Foo [concrete = constants.%Foo.generic] { +// CHECK:STDOUT: %Foo.decl.loc14: %Foo.type.09efb5.2 = interface_decl @Foo.loc14 [concrete = constants.%Foo.generic.dc5ede.2] { // CHECK:STDOUT: %a.patt: %pattern_type = symbolic_binding_pattern a, 0 [concrete] // CHECK:STDOUT: } { -// CHECK:STDOUT: %.loc7: type = splice_block %C.ref.loc7 [concrete = constants.%C] { -// CHECK:STDOUT: %.Self.loc7: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] -// CHECK:STDOUT: %C.ref.loc7: type = name_ref C, file.%C.decl [concrete = constants.%C] +// CHECK:STDOUT: %.loc14: type = splice_block %C.ref [concrete = constants.%C] { +// CHECK:STDOUT: %.Self: %type = symbolic_binding .Self [symbolic_self = constants.%.Self] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C] // CHECK:STDOUT: } -// CHECK:STDOUT: %a.loc7: %C = symbolic_binding a, 0 [symbolic = %a.loc6_16.1 (constants.%a)] +// CHECK:STDOUT: %a.loc14_16.2: %C = symbolic_binding a, 0 [symbolic = %a.loc14_16.1 (constants.%a)] // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic interface @Foo(%a.loc6_16.2: %C) { +// CHECK:STDOUT: generic interface @Foo.loc6(%a.loc6_16.2: %C) { // CHECK:STDOUT: %a.loc6_16.1: %C = symbolic_binding a, 0 [symbolic = %a.loc6_16.1 (constants.%a)] // CHECK:STDOUT: +// CHECK:STDOUT: interface; +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @Foo.loc14(%a.loc14_16.2: %C) { +// CHECK:STDOUT: %a.loc14_16.1: %C = symbolic_binding a, 0 [symbolic = %a.loc14_16.1 (constants.%a)] +// CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %Foo.type: type = facet_type <@Foo, @Foo(%a.loc6_16.1)> [symbolic = %Foo.type (constants.%Foo.type.01e)] -// CHECK:STDOUT: %Self.loc7_24.2: @Foo.%Foo.type (%Foo.type.01e) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self)] +// CHECK:STDOUT: %Foo.type: type = facet_type <@Foo.loc14, @Foo.loc14(%a.loc14_16.1)> [symbolic = %Foo.type (constants.%Foo.type.01e)] +// CHECK:STDOUT: %Self.loc14_24.2: @Foo.loc14.%Foo.type (%Foo.type.01e) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self)] // CHECK:STDOUT: // CHECK:STDOUT: interface { -// CHECK:STDOUT: %Self.loc7_24.1: @Foo.%Foo.type (%Foo.type.01e) = symbolic_binding Self, 1 [symbolic = %Self.loc7_24.2 (constants.%Self)] -// CHECK:STDOUT: %Foo.WithSelf.decl = interface_with_self_decl @Foo [concrete] +// CHECK:STDOUT: %Self.loc14_24.1: @Foo.loc14.%Foo.type (%Foo.type.01e) = symbolic_binding Self, 1 [symbolic = %Self.loc14_24.2 (constants.%Self)] +// CHECK:STDOUT: %Foo.WithSelf.decl = interface_with_self_decl @Foo.loc14 [concrete] // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = %Self.loc7_24.1 +// CHECK:STDOUT: .Self = %Self.loc14_24.1 // CHECK:STDOUT: witness = () // CHECK:STDOUT: // CHECK:STDOUT: !requires: @@ -547,10 +562,14 @@ interface Foo(a:! const (const C)) {} // CHECK:STDOUT: .Self = constants.%C // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: specific @Foo(constants.%a) { +// CHECK:STDOUT: specific @Foo.loc6(constants.%a) { // CHECK:STDOUT: %a.loc6_16.1 => constants.%a // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: specific @Foo.loc14(constants.%a) { +// CHECK:STDOUT: %a.loc14_16.1 => constants.%a +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: specific @Foo.WithSelf(constants.%a, constants.%Self) {} // CHECK:STDOUT: // CHECK:STDOUT: --- two_file.carbon diff --git a/toolchain/check/testdata/interop/cpp/class/import/template.carbon b/toolchain/check/testdata/interop/cpp/class/import/template.carbon index 069473406d2b..69456a6f03e8 100644 --- a/toolchain/check/testdata/interop/cpp/class/import/template.carbon +++ b/toolchain/check/testdata/interop/cpp/class/import/template.carbon @@ -67,7 +67,7 @@ var x: Cpp.XY.r#type = 0; // CHECK:STDERR: fail_use_instantiation_error.carbon:[[@LINE+12]]:8: error: member access into incomplete class `Cpp.X` [QualifiedExprInIncompleteClassScope] // CHECK:STDERR: var y: Cpp.Xint.r#type = 0; -// CHECK:STDERR: ^~~~~~~~~~~~~ +// CHECK:STDERR: ^~~~~~~~~~~~~~~ // CHECK:STDERR: fail_use_instantiation_error.carbon:[[@LINE-8]]:10: in file included here [InCppInclude] // CHECK:STDERR: ./instantiation_error.h:3:25: note: type 'int' cannot be used prior to '::' because it has no members [CppInteropParseError] // CHECK:STDERR: 3 | using type = typename T::member; diff --git a/toolchain/lex/testdata/fail_bad_raw_identifier.carbon b/toolchain/lex/testdata/fail_bad_raw_identifier.carbon index e3a6361e4626..22a456b3eb4e 100644 --- a/toolchain/lex/testdata/fail_bad_raw_identifier.carbon +++ b/toolchain/lex/testdata/fail_bad_raw_identifier.carbon @@ -47,7 +47,7 @@ r#รก // CHECK:STDERR: ^ // CHECK:STDERR: r#r#foo -// CHECK:STDOUT: - { index: 8, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r", identifier: 0, has_leading_space: true } +// CHECK:STDOUT: - { index: 8, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r#r", identifier: 0, has_leading_space: true } // CHECK:STDOUT: - { index: 9, kind: "Error", line: {{ *}}[[@LINE-2]], column: 4, indent: 1, spelling: "#" } // CHECK:STDOUT: - { index: 10, kind: "Identifier", line: {{ *}}[[@LINE-3]], column: 5, indent: 1, spelling: "foo", identifier: 1 } diff --git a/toolchain/lex/testdata/raw_identifier.carbon b/toolchain/lex/testdata/raw_identifier.carbon index 2a388ac3c527..279aec9af27d 100644 --- a/toolchain/lex/testdata/raw_identifier.carbon +++ b/toolchain/lex/testdata/raw_identifier.carbon @@ -12,7 +12,7 @@ // A non-keyword identifier. r#foo -// CHECK:STDOUT: - { index: 1, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "foo", identifier: 1, has_leading_space: true } +// CHECK:STDOUT: - { index: 1, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r#foo", identifier: 1, has_leading_space: true } // The same non-keyword identifier, for comparison. foo @@ -20,7 +20,7 @@ foo // A keyword as a raw identifier. r#self -// CHECK:STDOUT: - { index: 3, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "self", identifier: 2, has_leading_space: true } +// CHECK:STDOUT: - { index: 3, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r#self", identifier: 2, has_leading_space: true } // The same keyword, for comparison. self @@ -28,7 +28,7 @@ self // A type literal as a raw identifier. r#i32 -// CHECK:STDOUT: - { index: 5, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "i32", identifier: 3, has_leading_space: true } +// CHECK:STDOUT: - { index: 5, kind: "Identifier", line: {{ *}}[[@LINE-1]], column: 1, indent: 1, spelling: "r#i32", identifier: 3, has_leading_space: true } // The same type literal, for comparison. i32 diff --git a/toolchain/lex/tokenized_buffer.cpp b/toolchain/lex/tokenized_buffer.cpp index b02edb49866e..f23edde0e047 100644 --- a/toolchain/lex/tokenized_buffer.cpp +++ b/toolchain/lex/tokenized_buffer.cpp @@ -107,7 +107,18 @@ auto TokenizedBuffer::GetTokenText(TokenIndex token) const -> llvm::StringRef { CARBON_CHECK(token_info.kind() == TokenKind::Identifier, "{0}", token_info.kind()); - return value_stores_->identifiers().Get(token_info.ident_id()); + + // If this is a raw identifier, obtain its spelling from the source text. + auto ident = value_stores_->identifiers().Get(token_info.ident_id()); + if (IsRawIdentifier(token)) { + llvm::StringRef raw_ident = + source_->text().substr(token_info.byte_offset(), ident.size() + 2); + CARBON_CHECK(raw_ident[0] == 'r' && raw_ident[1] == '#' && + raw_ident.substr(2) == ident, + "`{0}` != `r#` + `{1}`", raw_ident, ident); + return raw_ident; + } + return ident; } auto TokenizedBuffer::GetIdentifier(TokenIndex token) const -> IdentifierId { @@ -170,6 +181,22 @@ auto TokenizedBuffer::GetMatchedOpeningToken(TokenIndex closing_token) const return closing_token_info.opening_token_index(); } +auto TokenizedBuffer::IsRawIdentifier(TokenIndex token) const -> bool { + const auto& token_info = token_infos_.Get(token); + if (token_info.kind() != TokenKind::Identifier) { + return false; + } + // Check if the spelling starts `r#`. A small nuance here: we also need to + // check the character after the `#` is an identifier start character, because + // `r#` is lexed as an `r` token followed by a token + // starting with `#`. It suffices to check that character is the first + // character of the identifier. + auto token_text = source_->text().substr(token_info.byte_offset()); + return token_text.starts_with("r#") && + token_text[2] == + value_stores_->identifiers().Get(token_info.ident_id()).front(); +} + auto TokenizedBuffer::IsRecoveryToken(TokenIndex token) const -> bool { if (recovery_tokens_.empty()) { return false; diff --git a/toolchain/lex/tokenized_buffer.h b/toolchain/lex/tokenized_buffer.h index 152d44ed3080..1d964b2088d4 100644 --- a/toolchain/lex/tokenized_buffer.h +++ b/toolchain/lex/tokenized_buffer.h @@ -168,6 +168,9 @@ class TokenizedBuffer : public Printable { // Returns whether the given token has trailing whitespace. auto HasTrailingWhitespace(TokenIndex token) const -> bool; + // Returns whether the token was spelled as a raw identifier. + auto IsRawIdentifier(TokenIndex token) const -> bool; + // Returns whether the token was created as part of an error recovery effort. // // For example, a closing paren inserted to match an unmatched paren. diff --git a/toolchain/parse/testdata/packages/library/fail_invalid_name.carbon b/toolchain/parse/testdata/packages/library/fail_invalid_name.carbon index 744efed8c585..9d15fabc1384 100644 --- a/toolchain/parse/testdata/packages/library/fail_invalid_name.carbon +++ b/toolchain/parse/testdata/packages/library/fail_invalid_name.carbon @@ -20,7 +20,7 @@ library Shapes; // CHECK:STDERR: fail_raw_identifier.carbon:[[@LINE+4]]:9: error: expected `default` or a string literal to specify the library name [ExpectedLibraryNameOrDefault] // CHECK:STDERR: library r#default; -// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: ^~~~~~~~~ // CHECK:STDERR: library r#default;