diff --git a/toolchain/check/cpp/generate_ast.cpp b/toolchain/check/cpp/generate_ast.cpp index 733b37bdf2ee..235377974045 100644 --- a/toolchain/check/cpp/generate_ast.cpp +++ b/toolchain/check/cpp/generate_ast.cpp @@ -25,8 +25,10 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" +#include "toolchain/base/kind_switch.h" #include "toolchain/check/context.h" #include "toolchain/check/cpp/import.h" +#include "toolchain/check/import_ref.h" #include "toolchain/check/name_lookup.h" #include "toolchain/diagnostics/diagnostic.h" #include "toolchain/diagnostics/emitter.h" @@ -384,26 +386,40 @@ auto CarbonExternalASTSource::MapInstIdToClangDecl( clang::DeclContext& decl_context, LookupResult lookup) -> clang::NamedDecl* { auto target_inst_id = lookup.scope_result.target_inst_id(); - if (auto target_inst = - context_->insts().TryGetAs(target_inst_id)) { - auto& name_scope = context_->name_scopes().Get(target_inst->name_scope_id); - auto* identifier_info = - GetClangIdentifierInfo(*context_, name_scope.name_id()); - // TODO: Don't immediately use the decl_context - build any intermediate - // namespaces iteratively. - // Eventually add a mapping and use that/populate it/keep it up to date. - // decl_context could be prepopulated in that mapping and not passed - // explicitly to MapInstIdToClangDecl. - auto* namespace_decl = clang::NamespaceDecl::Create( - *ast_context_, &decl_context, false, clang::SourceLocation(), - clang::SourceLocation(), identifier_info, nullptr, false); - auto result = - scope_map_.Insert(namespace_decl->getPrimaryContext(), target_inst_id); - CARBON_CHECK(result.is_inserted(), "Inserting over an existing entry."); - namespace_decl->setHasExternalVisibleStorage(); - return namespace_decl; + auto target_constant = + context_->constant_values().GetConstantInstId(target_inst_id); + auto target_inst = context_->insts().Get(target_constant); + CARBON_KIND_SWITCH(target_inst) { + case CARBON_KIND(SemIR::Namespace namespace_info): { + auto& name_scope = + context_->name_scopes().Get(namespace_info.name_scope_id); + auto* identifier_info = + GetClangIdentifierInfo(*context_, name_scope.name_id()); + // TODO: Don't immediately use the decl_context - build any intermediate + // namespaces iteratively. + // Eventually add a mapping and use that/populate it/keep it up to date. + // decl_context could be prepopulated in that mapping and not passed + // explicitly to MapInstIdToClangDecl. + auto* namespace_decl = clang::NamespaceDecl::Create( + *ast_context_, &decl_context, false, clang::SourceLocation(), + clang::SourceLocation(), identifier_info, nullptr, false); + auto result = scope_map_.Insert(namespace_decl->getPrimaryContext(), + target_inst_id); + CARBON_CHECK(result.is_inserted(), "Inserting over an existing entry."); + namespace_decl->setHasExternalVisibleStorage(); + return namespace_decl; + } + case CARBON_KIND(SemIR::ClassType class_type): { + const auto& class_info = context_->classes().Get(class_type.class_id); + auto* identifier_info = + GetClangIdentifierInfo(*context_, class_info.name_id); + return clang::CXXRecordDecl::Create( + *ast_context_, clang::TagTypeKind::Class, &decl_context, + clang::SourceLocation(), clang::SourceLocation(), identifier_info); + } + default: + return nullptr; } - return nullptr; } auto CarbonExternalASTSource::FindExternalVisibleDeclsByName( diff --git a/toolchain/check/testdata/interop/cpp/reverse/simple.carbon b/toolchain/check/testdata/interop/cpp/reverse/simple.carbon index 89f8aea0122d..a6dcca482860 100644 --- a/toolchain/check/testdata/interop/cpp/reverse/simple.carbon +++ b/toolchain/check/testdata/interop/cpp/reverse/simple.carbon @@ -14,6 +14,8 @@ package Other; namespace Nested; namespace Nested.Again; + +class Class1; // --- namespace.carbon library "[[@TEST_NAME]]"; @@ -23,4 +25,14 @@ import Cpp inline ''' namespace X = Carbon::Other; namespace Y = Carbon::Other::Nested; namespace Z = Carbon::Other::Nested::Again; +Carbon::Other::Class1 *glbl; + +template void f1() { + T* v; +} + +void f2() { + f1(); +} + '''; diff --git a/toolchain/lower/testdata/interop/cpp/reverse/mangle_type.carbon b/toolchain/lower/testdata/interop/cpp/reverse/mangle_type.carbon new file mode 100644 index 000000000000..b9b77aa3bf4d --- /dev/null +++ b/toolchain/lower/testdata/interop/cpp/reverse/mangle_type.carbon @@ -0,0 +1,71 @@ +// 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/none.carbon +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/lower/testdata/interop/cpp/reverse/mangle_type.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/interop/cpp/reverse/mangle_type.carbon + +// --- other.carbon +package Other; + +class Class1; +// --- namespace.carbon + +library "[[@TEST_NAME]]"; + +import Other; +import Cpp inline ''' + +void f1(Carbon::Other::Class1*) { +} + +'''; + +// CHECK:STDOUT: ; ModuleID = 'other.carbon' +// CHECK:STDOUT: source_filename = "other.carbon" +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1} +// CHECK:STDOUT: !llvm.dbg.cu = !{!2} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !3 = !DIFile(filename: "other.carbon", directory: "") +// CHECK:STDOUT: ; ModuleID = 'namespace.carbon' +// CHECK:STDOUT: source_filename = "namespace.carbon" +// CHECK:STDOUT: target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" +// CHECK:STDOUT: target triple = "x86_64-unknown-linux-gnu" +// CHECK:STDOUT: +// CHECK:STDOUT: ; Function Attrs: mustprogress nounwind uwtable +// CHECK:STDOUT: define dso_local void @_Z2f1PN6Carbon5Other6Class1E(ptr noundef %0) #0 { +// CHECK:STDOUT: entry: +// CHECK:STDOUT: %.addr = alloca ptr, align 8 +// CHECK:STDOUT: store ptr %0, ptr %.addr, align 8, !tbaa !11 +// CHECK:STDOUT: ret void +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: attributes #0 = { mustprogress nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } +// CHECK:STDOUT: +// CHECK:STDOUT: !llvm.module.flags = !{!0, !1, !2, !3, !4} +// CHECK:STDOUT: !llvm.dbg.cu = !{!5} +// CHECK:STDOUT: !llvm.errno.tbaa = !{!7} +// CHECK:STDOUT: +// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5} +// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3} +// CHECK:STDOUT: !2 = !{i32 8, !"PIC Level", i32 2} +// CHECK:STDOUT: !3 = !{i32 7, !"PIE Level", i32 2} +// CHECK:STDOUT: !4 = !{i32 7, !"uwtable", i32 2} +// CHECK:STDOUT: !5 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !6, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug) +// CHECK:STDOUT: !6 = !DIFile(filename: "namespace.carbon", directory: "") +// CHECK:STDOUT: !7 = !{!8, !8, i64 0} +// CHECK:STDOUT: !8 = !{!"int", !9, i64 0} +// CHECK:STDOUT: !9 = !{!"omnipotent char", !10, i64 0} +// CHECK:STDOUT: !10 = !{!"Simple C++ TBAA"} +// CHECK:STDOUT: !11 = !{!12, !12, i64 0} +// CHECK:STDOUT: !12 = !{!"p1 _ZTSN6Carbon5Other6Class1E", !13, i64 0} +// CHECK:STDOUT: !13 = !{!"any pointer", !9, i64 0}