Don't crash if a macro expands to an erroneous expression. (#7652)

For certain kinds of error, clang's parser will succeed but produce an
expression marked as "contains error". Clang's constant evaluator
asserts if given one of those, so return early if we encounter one.
This commit is contained in:
Richard Smith
2026-08-19 00:47:03 +00:00
committed by GitHub
parent d21cc3197f
commit 047555bb1c
2 changed files with 59 additions and 1 deletions
+1 -1
View File
@@ -84,7 +84,7 @@ auto TryEvaluateMacro(Context& context, SemIR::LocId loc_id,
parser.ConsumeAnyToken(true);
}
if (!success) {
if (!success || result_expr->containsErrors()) {
CARBON_DIAGNOSTIC(
InCppMacroEvaluation, Error,
"failed to parse macro Cpp.{0} to a valid constant expression",
@@ -0,0 +1,58 @@
// 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/macros/invalid.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/interop/cpp/macros/invalid.carbon
// --- fail_macro_with_error.carbon
library "[[@TEST_NAME]]";
import Cpp inline '''
// CHECK:STDERR: fail_macro_with_error.carbon:[[@LINE+4]]:1: error: unknown type name 'error' [CppInteropParseError]
// CHECK:STDERR: 9 | error has_error;
// CHECK:STDERR: | ^
// CHECK:STDERR:
error has_error;
#define macro_with_error has_error.member
''';
fn F() {
//@dump-sem-ir-begin
// CHECK:STDERR: fail_macro_with_error.carbon:[[@LINE+11]]:3: error: failed to parse macro Cpp.macro_with_error to a valid constant expression [InCppMacroEvaluation]
// CHECK:STDERR: Cpp.macro_with_error;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_macro_with_error.carbon:[[@LINE+8]]:3: note: in `Cpp` name lookup for `macro_with_error` [InCppNameLookup]
// CHECK:STDERR: Cpp.macro_with_error;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
// CHECK:STDERR: fail_macro_with_error.carbon:[[@LINE+4]]:3: error: member name `macro_with_error` not found in `Cpp` [MemberNameNotFoundInInstScope]
// CHECK:STDERR: Cpp.macro_with_error;
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~
// CHECK:STDERR:
Cpp.macro_with_error;
//@dump-sem-ir-end
}
// CHECK:STDOUT: --- fail_macro_with_error.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Cpp: <namespace> = namespace file.%Cpp.import_cpp, [concrete] {
// CHECK:STDOUT: .macro_with_error = <poisoned>
// CHECK:STDOUT: import Cpp//...
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Cpp.ref: <namespace> = name_ref Cpp, imports.%Cpp [concrete = imports.%Cpp]
// CHECK:STDOUT: %macro_with_error.ref: <error> = name_ref macro_with_error, <error> [concrete = <error>]
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT: