C++ interop: Don't crash when looking up names inside an incomplete C++ class/struct/union (#6096)

Only do the lookup when the class is complete.

Before this change we crash in `Sema::LookupQualifiedName()` on
`Declaration context must already be complete!`.
This commit is contained in:
Boaz Brickner
2025-09-18 22:03:42 +00:00
committed by GitHub
parent d137cbe1f1
commit 868c4b768c
5 changed files with 113 additions and 0 deletions
@@ -341,6 +341,32 @@ fn F() {
//@dump-sem-ir-end
}
// ============================================================================
// Incomplete class
// ============================================================================
// --- incomplete.h
class Incomplete;
// --- fail_import_incomplete.carbon
library "[[@TEST_NAME]]";
import Cpp library "incomplete.h";
fn F() {
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE+8]]:3: error: member access into incomplete class `Cpp.Incomplete` [QualifiedExprInIncompleteClassScope]
// CHECK:STDERR: Cpp.Incomplete.foo();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./incomplete.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: class Incomplete;
// CHECK:STDERR: ^
// CHECK:STDERR:
Cpp.Incomplete.foo();
}
// ============================================================================
// Pointer to forward-declared class as parameter type
// ============================================================================
@@ -339,6 +339,32 @@ fn F() {
//@dump-sem-ir-end
}
// ============================================================================
// Incomplete struct
// ============================================================================
// --- incomplete.h
struct Incomplete;
// --- fail_import_incomplete.carbon
library "[[@TEST_NAME]]";
import Cpp library "incomplete.h";
fn F() {
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE+8]]:3: error: member access into incomplete class `Cpp.Incomplete` [QualifiedExprInIncompleteClassScope]
// CHECK:STDERR: Cpp.Incomplete.foo();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./incomplete.h:2:8: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: struct Incomplete;
// CHECK:STDERR: ^
// CHECK:STDERR:
Cpp.Incomplete.foo();
}
// ============================================================================
// Pointer to forward-declared struct as parameter type
// ============================================================================
@@ -302,6 +302,32 @@ fn F() {
//@dump-sem-ir-end
}
// ============================================================================
// Incomplete union
// ============================================================================
// --- incomplete.h
union Incomplete;
// --- fail_import_incomplete.carbon
library "[[@TEST_NAME]]";
import Cpp library "incomplete.h";
fn F() {
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE+8]]:3: error: member access into incomplete class `Cpp.Incomplete` [QualifiedExprInIncompleteClassScope]
// CHECK:STDERR: Cpp.Incomplete.foo();
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~
// CHECK:STDERR: fail_import_incomplete.carbon:[[@LINE-6]]:10: in file included here [InCppInclude]
// CHECK:STDERR: ./incomplete.h:2:7: note: class was forward declared here [ClassForwardDeclaredHere]
// CHECK:STDERR: union Incomplete;
// CHECK:STDERR: ^
// CHECK:STDERR:
Cpp.Incomplete.foo();
}
// ============================================================================
// Pointer to forward-declared union as parameter type
// ============================================================================