C++ interop: Add Cpp.<builtin_type> (#6047)

Based on proposal #5448.

Defining all `Cpp.<builtin_type>` names.
Still unsupported types on LP64: `long long`, `unsigned long long` and
`long double`.
Still unsupported types on LLP64: `long`, `unsigned long` and `long
double`.

C++ Interop Demo (on LP64):

```c++
// half.h

auto Half(long x) -> float;
auto PrintLong(long x) -> void;
auto PrintFloat(float x) -> void;
```

```c++
// half.cpp

#include <cstdio>

auto Half(long x) -> float {
  return static_cast<float>(x) / 2;
}

auto PrintLong(long x) -> void {
  printf("%ld\n", x);
}

auto PrintFloat(float x) -> void {
  printf("%f\n", x);
}
```

```carbon
// main.carbon

library "Main";

import Cpp library "half.h";

fn Run() -> i32 {
  let x: Cpp.long = 5;
  Cpp.PrintLong(x);
  let y: Cpp.float = Cpp.Half(x);
  Cpp.PrintFloat(y);
  return 0;
}
```

```shell
$ clang -c half.cpp
$ bazel-bin/toolchain/carbon compile main.carbon
$ bazel-bin/toolchain/carbon link half.o main.o --output=demo
$ ./demo
5
2.500000
```

Part of #5263.
This commit is contained in:
Boaz Brickner
2025-09-16 09:29:10 +00:00
committed by GitHub
parent 170237b9e0
commit 9b35640a31
4 changed files with 1208 additions and 0 deletions
+63
View File
@@ -1970,6 +1970,61 @@ static auto ImportNameDeclIntoScope(Context& context, SemIR::LocId loc_id,
access_kind);
}
// Returns true if the scope is the top `Cpp` scope.
static auto IsTopCppScope(Context& context, SemIR::NameScopeId scope_id)
-> bool {
const SemIR::NameScope& name_scope = context.name_scopes().Get(scope_id);
CARBON_CHECK(name_scope.is_cpp_scope());
return name_scope.parent_scope_id() == SemIR::NameScopeId::Package;
}
// For builtin names like `Cpp.long`, return the associated types.
static auto LookupBuiltInTypes(Context& context, SemIR::LocId loc_id,
SemIR::NameScopeId scope_id,
SemIR::NameId name_id) -> SemIR::InstId {
if (!IsTopCppScope(context, scope_id)) {
return SemIR::InstId::None;
}
auto name = context.names().GetAsStringIfIdentifier(name_id);
if (!name) {
return SemIR::InstId::None;
}
const clang::ASTContext& ast_context = context.ast_context();
// List of types based on
// https://github.com/carbon-language/carbon-lang/blob/trunk/proposals/p5448.md#details
auto builtin_type =
llvm::StringSwitch<clang::QualType>(*name)
.Case("signed_char", ast_context.SignedCharTy)
.Case("short", ast_context.ShortTy)
.Case("int", ast_context.IntTy)
.Case("long", ast_context.LongTy)
.Case("long_long", ast_context.LongLongTy)
.Case("unsigned_char", ast_context.UnsignedCharTy)
.Case("unsigned_short", ast_context.UnsignedShortTy)
.Case("unsigned_int", ast_context.UnsignedIntTy)
.Case("unsigned_long", ast_context.UnsignedLongTy)
.Case("unsigned_long_long", ast_context.UnsignedLongLongTy)
.Case("float", ast_context.FloatTy)
.Case("double", ast_context.DoubleTy)
.Case("long_double", ast_context.LongDoubleTy)
.Default(clang::QualType());
if (builtin_type.isNull()) {
return SemIR::InstId::None;
}
SemIR::InstId inst_id =
MapNonWrapperType(context, loc_id, builtin_type).inst_id;
if (!inst_id.has_value()) {
context.TODO(loc_id, llvm::formatv("Unsupported: builtin type: {0}",
builtin_type.getAsString()));
return SemIR::ErrorInst::InstId;
}
return inst_id;
}
// Imports an overloaded function set from Clang to Carbon.
static auto ImportCppOverloadSet(Context& context, SemIR::NameScopeId scope_id,
SemIR::NameId name_id,
@@ -2058,6 +2113,14 @@ auto ImportNameFromCpp(Context& context, SemIR::LocId loc_id,
auto lookup = ClangLookupName(context, scope_id, name_id);
if (!lookup) {
SemIR::InstId builtin_inst_id =
LookupBuiltInTypes(context, loc_id, scope_id, name_id);
if (builtin_inst_id.has_value()) {
AddNameToScope(context, scope_id, name_id, SemIR::AccessKind::Public,
builtin_inst_id);
return SemIR::ScopeLookupResult::MakeWrappedLookupResult(
builtin_inst_id, SemIR::AccessKind::Public);
}
return SemIR::ScopeLookupResult::MakeNotFound();
}