Ver código fonte

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 <danakj@orodu.net>
Richard Smith 8 meses atrás
pai
commit
4483d1e5a7

+ 5 - 0
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.

+ 31 - 0
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;

+ 27 - 0
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;