Files
carbon-lang/toolchain/check/testdata/interop/cpp/template/template_template_param.carbon
T
Geoff RomerandDana Jansens e67b6db910 Give files shorthand names in textual SemIR (#8104)
Shorthand names are intended to be used in the textual format of
references to instructions in another IR (which can't happen now, but
will be possible in a forthcoming PR). The shorthand name uses the file
name (minus the `.carbon` suffix) as a base, and if that base name is
ambiguous within the compilation, it is given a numerical suffix `.N`,
just like other textual IR names. Shorthand names are prefixed with `$`
in the textual format, to distinguish them from inst and scope names.

For example, a file `foo/bar.carbon` has the shorthand name `$bar`, and
an instruction `@baz.%qux` in that file can be referenced from another
file as `$bar.@baz.%qux`.

This PR adds `toolchain/check/testdata/basics/file_name.carbon` to test
this behavior. All other test changes are just applying this change to
the existing textual SemIR dumps.

---------

Co-authored-by: Dana Jansens <danakj@orodu.net>
2026-11-12 23:34:32 +00:00

171 lines
9.8 KiB
Plaintext

// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/convert.carbon
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/interop/cpp/template/template_template_param.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/template/template_template_param.carbon
// --- templates.h
template<typename> struct A {};
template<typename> struct B {};
template<typename, typename> struct C {};
template<template<typename> typename, template<typename> typename>
struct TwoTemplates {};
// --- valid.carbon
library "[[@TEST_NAME]]";
import Cpp library "templates.h";
//@dump-sem-ir-begin
var x: Cpp.TwoTemplates(Cpp.A, Cpp.B);
//@dump-sem-ir-end
// --- fail_template_mismatch.carbon
library "[[@TEST_NAME]]";
import Cpp library "templates.h";
//@dump-sem-ir-begin
// CHECK:STDERR: ╭─┤ fail_template_mismatch.carbon:[[@LINE+28]]:35
// CHECK:STDERR: -> │ var x: Cpp.TwoTemplates(Cpp.A, Cpp.C);
// CHECK:STDERR: · ┳
// CHECK:STDERR: · ┗━━┫ error: too few template arguments for
// CHECK:STDERR: · │ ┃ class template 'C'
// CHECK:STDERR: · │ ┃ [CppInteropParseError]
// CHECK:STDERR: · ╰────┤ template template argument has
// CHECK:STDERR: · │ different template parameters than its
// CHECK:STDERR: · │ corresponding template template
// CHECK:STDERR: · │ parameter
// CHECK:STDERR: · │ [CppInteropParseNote]
// CHECK:STDERR: ┆
// CHECK:STDERR: ├─┤ ./templates.h
// CHECK:STDERR: │ template<typename, typename> struct C {};
// CHECK:STDERR: · ──────────────────────────── ┬
// CHECK:STDERR: · ╰──┤ template is declared here
// CHECK:STDERR: · │ [CppInteropParseNote]
// CHECK:STDERR: │
// CHECK:STDERR: │ template<template<typename> typename, template<typename> typename>
// CHECK:STDERR: · ────────────────── ┬
// CHECK:STDERR: · ╰──┤ previous
// CHECK:STDERR: · │ template
// CHECK:STDERR: · │ template
// CHECK:STDERR: · │ parameter
// CHECK:STDERR: · │ is here
// CHECK:STDERR: · │ [CppInteropParseNote]
// CHECK:STDERR: ╰────
// CHECK:STDERR:
var x: Cpp.TwoTemplates(Cpp.A, Cpp.C);
//@dump-sem-ir-end
// --- fail_type_argument.carbon
library "[[@TEST_NAME]]";
import Cpp library "templates.h";
class X {}
// CHECK:STDERR: ╭─┤ fail_type_argument.carbon:[[@LINE+9]]:32
// CHECK:STDERR: -> │ var x: Cpp.TwoTemplates(Cpp.A, X);
// CHECK:STDERR: · ┳
// CHECK:STDERR: · ┗━━┫ error: template argument for template
// CHECK:STDERR: · ┃ template parameter must be a class
// CHECK:STDERR: · ┃ template or type alias template
// CHECK:STDERR: · ┃ [CppInteropParseError]
// CHECK:STDERR: ╰────
// CHECK:STDERR:
var x: Cpp.TwoTemplates(Cpp.A, X);
// --- fail_non_type_argument.carbon
library "[[@TEST_NAME]]";
import Cpp library "templates.h";
// CHECK:STDERR: ╭─┤ fail_non_type_argument.carbon:[[@LINE+9]]:32
// CHECK:STDERR: -> │ var x: Cpp.TwoTemplates(Cpp.A, true);
// CHECK:STDERR: · ┳
// CHECK:STDERR: · ┗━━┫ error: template argument for template
// CHECK:STDERR: · ┃ template parameter must be a class
// CHECK:STDERR: · ┃ template or type alias template
// CHECK:STDERR: · ┃ [CppInteropParseError]
// CHECK:STDERR: ╰────
// CHECK:STDERR:
var x: Cpp.TwoTemplates(Cpp.A, true);
// CHECK:STDOUT: --- valid.carbon = $valid
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: type: type = facet_type <type> [concrete]
// CHECK:STDOUT: %TwoTemplates: type = class_type @TwoTemplates [concrete]
// CHECK:STDOUT: %pattern_type.f5e: type = pattern_type %TwoTemplates [concrete]
// CHECK:STDOUT: %x.patt: %pattern_type.f5e = ref_binding_pattern x [concrete]
// CHECK:STDOUT: %x.var_patt: %pattern_type.f5e = var_pattern %x.patt [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.type: type = facet_type <@DefaultOrUnformed> [concrete]
// CHECK:STDOUT: %Default.type: type = facet_type <@Default> [concrete]
// CHECK:STDOUT: %T.b09: %Default.type = symbolic_binding T, 0 [symbolic]
// CHECK:STDOUT: %T.as_type.as.DefaultOrUnformed.impl.Op.type.4da: type = fn_type @T.as_type.as.DefaultOrUnformed.impl.Op, @T.as_type.as.DefaultOrUnformed.impl(%T.b09) [symbolic]
// CHECK:STDOUT: %T.as_type.as.DefaultOrUnformed.impl.Op.79f: %T.as_type.as.DefaultOrUnformed.impl.Op.type.4da = struct_value () [symbolic]
// CHECK:STDOUT: %TwoTemplates.Op.type: type = fn_type @TwoTemplates.Op [concrete]
// CHECK:STDOUT: %TwoTemplates.Op: %TwoTemplates.Op.type = struct_value () [concrete]
// CHECK:STDOUT: %custom_witness.9b4: <witness> = custom_witness (%TwoTemplates.Op), @Default [concrete]
// CHECK:STDOUT: %Default.facet.e75: %Default.type = facet_value %TwoTemplates, (%custom_witness.9b4) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness.436: <witness> = impl_witness imports.%DefaultOrUnformed.impl_witness_table.162, @T.as_type.as.DefaultOrUnformed.impl(%Default.facet.e75) [concrete]
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value %TwoTemplates, (%DefaultOrUnformed.impl_witness.436) [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core.import_ref.288: @T.as_type.as.DefaultOrUnformed.impl.%T.as_type.as.DefaultOrUnformed.impl.Op.type (%T.as_type.as.DefaultOrUnformed.impl.Op.type.4da) = import_ref Core//prelude/parts/default, loc{{\d+_\d+}}, loaded [symbolic = @T.as_type.as.DefaultOrUnformed.impl.%T.as_type.as.DefaultOrUnformed.impl.Op (constants.%T.as_type.as.DefaultOrUnformed.impl.Op.79f)]
// CHECK:STDOUT: %DefaultOrUnformed.impl_witness_table.162 = impl_witness_table (%Core.import_ref.288), @T.as_type.as.DefaultOrUnformed.impl [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %x.var: ref %TwoTemplates = var_storage %x.var_patt [concrete]
// CHECK:STDOUT: %x: ref %TwoTemplates = wrapper_binding x, %x.var [concrete = %x.var]
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.f5e = ref_binding_pattern x [concrete = constants.%x.patt]
// CHECK:STDOUT: %x.var_patt: %pattern_type.f5e = var_pattern %x.patt [concrete = constants.%x.var_patt]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %DefaultOrUnformed.facet: %DefaultOrUnformed.type = facet_value constants.%TwoTemplates, (constants.%DefaultOrUnformed.impl_witness.436) [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %.loc7_38.1: %DefaultOrUnformed.type = converted constants.%TwoTemplates, %DefaultOrUnformed.facet [concrete = constants.%DefaultOrUnformed.facet]
// CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_38.1 [concrete = constants.%TwoTemplates]
// CHECK:STDOUT: %.loc7_38.2: type = converted %.loc7_38.1, %as_type [concrete = constants.%TwoTemplates]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %.loc7_1: ref %TwoTemplates = splice_block file.%x.var [concrete = file.%x.var] {}
// CHECK:STDOUT: %T.as_type.as.DefaultOrUnformed.impl.Op.call: init %TwoTemplates to %.loc7_1 = call %T.as_type.as.DefaultOrUnformed.impl.Op.specific_fn()
// CHECK:STDOUT: assign file.%x.var, %T.as_type.as.DefaultOrUnformed.impl.Op.call
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- fail_template_mismatch.carbon = $fail_template_mismatch
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: %x.var: ref <error> = var_storage %x.var_patt [concrete = <error>]
// CHECK:STDOUT: %x: <error> = wrapper_binding x, <error> [concrete = <error>]
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: <error> = ref_binding_pattern x [concrete = <error>]
// CHECK:STDOUT: %x.var_patt: <error> = var_pattern %x.patt [concrete = <error>]
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: assign file.%x.var, <error>
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: