From 4483d1e5a7156402a37a79ae0e4ad1f25b2fcf43 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 2 Sep 2025 12:32:35 -0700 Subject: [PATCH] Recover better from invalid C++ classes. (#5992) When importing a class definition, don't ask for the class layout if the definition is invalid. Avoids an assertion failure in Clang. --------- Co-authored-by: Dana Jansens --- toolchain/check/import_cpp.cpp | 5 +++ .../testdata/interop/cpp/class/invalid.carbon | 31 +++++++++++++++++++ .../testdata/interop/cpp/enum/invalid.carbon | 27 ++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 toolchain/check/testdata/interop/cpp/class/invalid.carbon create mode 100644 toolchain/check/testdata/interop/cpp/enum/invalid.carbon diff --git a/toolchain/check/import_cpp.cpp b/toolchain/check/import_cpp.cpp index be96385ffea1..d63f08656edc 100644 --- a/toolchain/check/import_cpp.cpp +++ b/toolchain/check/import_cpp.cpp @@ -825,6 +825,11 @@ static auto ImportClassObjectRepr(Context& context, SemIR::ClassId class_id, SemIR::TypeInstId class_type_inst_id, const clang::CXXRecordDecl* clang_def) -> SemIR::TypeInstId { + if (clang_def->isInvalidDecl()) { + // Clang already diagnosed this error. + return SemIR::ErrorInst::TypeInstId; + } + // For now, if the class is empty, produce an empty struct as the object // representation. This allows our tests to continue to pass while we don't // properly support initializing imported C++ classes. diff --git a/toolchain/check/testdata/interop/cpp/class/invalid.carbon b/toolchain/check/testdata/interop/cpp/class/invalid.carbon new file mode 100644 index 000000000000..fa7b1234e75e --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/class/invalid.carbon @@ -0,0 +1,31 @@ +// 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/primitives.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/class/invalid.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/class/invalid.carbon + +// --- fail_invalid_base.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +struct Base { + // CHECK:STDERR: fail_invalid_base.carbon:[[@LINE+4]]:3: error: unknown type name 'no_such_type' [CppInteropParseError] + // CHECK:STDERR: 10 | no_such_type invalid; + // CHECK:STDERR: | ^ + // CHECK:STDERR: + no_such_type invalid; +}; + +struct Derived : Base {}; +'''; + +// Use of an invalid class should not cause the toolchain to crash or produce +// redundant diagnostics. +var x: Cpp.Derived; diff --git a/toolchain/check/testdata/interop/cpp/enum/invalid.carbon b/toolchain/check/testdata/interop/cpp/enum/invalid.carbon new file mode 100644 index 000000000000..508be3d306b2 --- /dev/null +++ b/toolchain/check/testdata/interop/cpp/enum/invalid.carbon @@ -0,0 +1,27 @@ +// 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/primitives.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/enum/invalid.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/enum/invalid.carbon + +// --- fail_invalid_underlying_type.carbon + +library "[[@TEST_NAME]]"; + +import Cpp inline ''' +// CHECK:STDERR: fail_invalid_underlying_type.carbon:[[@LINE+4]]:20: error: unknown type name 'no_such_type' [CppInteropParseError] +// CHECK:STDERR: 9 | enum InvalidEnum : no_such_type {}; +// CHECK:STDERR: | ^ +// CHECK:STDERR: +enum InvalidEnum : no_such_type {}; +'''; + +// Use of an invalid enum should not cause the toolchain to crash or produce +// redundant diagnostics. +var x: Cpp.InvalidEnum;