Skip to content

Commit 8adb357

Browse files
authored
C++ Interop: Add support for char (#5988)
Added tests for different character types. `char` is currently not in primitives prelude, so had to use full prelude. C++ Interop Demo: ```carbon // main.carbon library "Main"; import Cpp inline ''' auto output_char(char c) -> void { printf("%c", c); } '''; fn Run() -> i32 { let msg: array(Core.Char, 13) = ('H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n'); for (c: Core.Char in msg) { Cpp.output_char(c); } return 0; } ``` ```shell $ bazel-bin/toolchain/carbon compile main.carbon $ bazel-bin/toolchain/carbon link main.o --output=demo $ ./demo Hello world! ``` Part of #5263.
1 parent 50e5476 commit 8adb357

File tree

5 files changed

+596
-64
lines changed

5 files changed

+596
-64
lines changed

toolchain/check/import_cpp.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,35 @@ static auto MakeIntType(Context& context, IntId size_id, bool is_signed)
11581158
return ExprAsType(context, Parse::NodeId::None, type_inst_id);
11591159
}
11601160

1161+
// Maps a C++ builtin integer type to a Carbon type.
1162+
// TODO: Handle integer types that map to named aliases.
1163+
static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
1164+
clang::QualType qual_type,
1165+
const clang::BuiltinType& type) -> TypeExpr {
1166+
clang::ASTContext& ast_context = context.ast_context();
1167+
unsigned width = ast_context.getIntWidth(qual_type);
1168+
bool is_signed = type.isSignedInteger();
1169+
auto int_n_type = ast_context.getIntTypeForBitwidth(width, is_signed);
1170+
if (ast_context.hasSameType(qual_type, int_n_type)) {
1171+
TypeExpr type_expr =
1172+
MakeIntType(context, context.ints().Add(width), is_signed);
1173+
// Try to make sure integer types of 32 or 64 bits are complete so we can
1174+
// check against them when deciding whether we need to generate a thunk.
1175+
if (width == 32 || width == 64) {
1176+
SemIR::TypeId type_id = type_expr.type_id;
1177+
if (!context.types().IsComplete(type_id)) {
1178+
TryToCompleteType(context, type_id, loc_id);
1179+
}
1180+
}
1181+
return type_expr;
1182+
}
1183+
if (ast_context.hasSameType(qual_type, ast_context.CharTy)) {
1184+
return ExprAsType(context, Parse::NodeId::None,
1185+
MakeCharTypeLiteral(context, Parse::NodeId::None));
1186+
}
1187+
return TypeExpr::None;
1188+
}
1189+
11611190
// Maps a C++ builtin type to a Carbon type.
11621191
// TODO: Support more builtin types.
11631192
static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
@@ -1171,25 +1200,9 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
11711200
context, SemIR::BoolType::TypeInstId)));
11721201
}
11731202
if (type.isInteger()) {
1174-
unsigned width = context.ast_context().getIntWidth(qual_type);
1175-
bool is_signed = type.isSignedInteger();
1176-
auto int_n_type =
1177-
context.ast_context().getIntTypeForBitwidth(width, is_signed);
1178-
if (context.ast_context().hasSameType(qual_type, int_n_type)) {
1179-
TypeExpr type_expr =
1180-
MakeIntType(context, context.ints().Add(width), is_signed);
1181-
// Try to make sure integer types of 32 or 64 bits are complete so we can
1182-
// check against them when deciding whether we need to generate a thunk.
1183-
if (width == 32 || width == 64) {
1184-
SemIR::TypeId type_id = type_expr.type_id;
1185-
if (!context.types().IsComplete(type_id)) {
1186-
TryToCompleteType(context, type_id, loc_id);
1187-
}
1188-
}
1189-
return type_expr;
1190-
}
1191-
// TODO: Handle integer types that map to named aliases.
1192-
} else if (type.isFloatingPoint()) {
1203+
return MapBuiltinIntegerType(context, loc_id, qual_type, type);
1204+
}
1205+
if (type.isFloatingPoint()) {
11931206
if (type.isFloat16Type() || type.isFloat32Type() || type.isDoubleType() ||
11941207
type.isFloat128Type()) {
11951208
return ExprAsType(

toolchain/check/literal.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)
2525
.int_id = int_id});
2626
}
2727

28+
auto MakeCharTypeLiteral(Context& context, Parse::NodeId node_id)
29+
-> SemIR::InstId {
30+
return LookupNameInCore(context, node_id, "Char");
31+
}
32+
2833
auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,
2934
SemIR::IntKind int_kind, IntId size_id)
3035
-> SemIR::InstId {

toolchain/check/literal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ namespace Carbon::Check {
1818
auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)
1919
-> SemIR::InstId;
2020

21+
// Forms a char type expression for `char` literal.
22+
auto MakeCharTypeLiteral(Context& context, Parse::NodeId node_id)
23+
-> SemIR::InstId;
24+
2125
// Forms an integer type expression for either an `iN` or `uN` literal.
2226
auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,
2327
SemIR::IntKind int_kind, IntId size_id)

toolchain/check/testdata/interop/cpp/class/field.carbon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Exceptions. See /LICENSE for license information.
33
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
44
//
5-
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/primitives.carbon
5+
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/full.carbon
66
//
77
// AUTOUPDATE
88
// TIP: To test this file alone, run:

0 commit comments

Comments
 (0)