Skip to content

Commit 9e73edf

Browse files
committed
C++ Interop: Support getting void* from C++ functions and passing void* it to C++ function
This defines `Cpp.void` as a custom type. `Cpp.void*` is mapped to C++ `void*`. Not supported yet: Conversions from and to other pointer types.
1 parent 53ea894 commit 9e73edf

24 files changed

+2462
-1986
lines changed

toolchain/check/cpp/import.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,10 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
11371137
context.ints().Add(ast_context.getTypeSize(qual_type))));
11381138
}
11391139
// TODO: Handle floating-point types that map to named aliases.
1140+
} else if (type.isVoidType()) {
1141+
return ExprAsType(context, Parse::NodeId::None,
1142+
context.types().GetInstId(GetSingletonType(
1143+
context, SemIR::CustomCppVoidType::TypeInstId)));
11401144
}
11411145

11421146
return TypeExpr::None;
@@ -2074,6 +2078,7 @@ static auto LookupBuiltinTypes(Context& context, SemIR::LocId loc_id,
20742078
.Case("float", ast_context.FloatTy)
20752079
.Case("double", ast_context.DoubleTy)
20762080
.Case("long_double", ast_context.LongDoubleTy)
2081+
.Case("void", ast_context.VoidTy)
20772082
.Default(clang::QualType());
20782083
if (builtin_type.isNull()) {
20792084
return SemIR::InstId::None;

toolchain/check/cpp/type_mapping.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,22 @@ static auto MapNonWrapperType(Context& context, SemIR::InstId inst_id,
180180
}
181181
}
182182

183+
// If `type_id` is `Cpp.void` and the last wrapper type in `wrapper_types` is a
184+
// pointer, pops the pointer wrapper and returns non nullable `void*` QualType.
185+
// Otherwise returns a null QualType.
186+
static auto TryMapVoidPointer(Context& context, SemIR::TypeId type_id,
187+
llvm::SmallVector<SemIR::TypeId>& wrapper_types)
188+
-> clang::QualType {
189+
if (type_id == SemIR::CustomCppVoidType::TypeId && !wrapper_types.empty() &&
190+
context.types().Is<SemIR::PointerType>(wrapper_types.back())) {
191+
wrapper_types.pop_back();
192+
return context.ast_context().getAttributedType(
193+
clang::attr::TypeNonNull, context.ast_context().VoidPtrTy,
194+
context.ast_context().VoidPtrTy);
195+
}
196+
return clang::QualType();
197+
}
198+
183199
// Maps a Carbon type to a C++ type. Accepts an InstId, representing a value
184200
// whose type is mapped to a C++ type. Returns `clang::QualType` if the mapping
185201
// succeeds, or `clang::QualType::isNull()` if the type is not supported.
@@ -204,9 +220,13 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
204220
wrapper_types.push_back(orig_type_id);
205221
}
206222

207-
clang::QualType mapped_type = MapNonWrapperType(context, inst_id, type_id);
223+
clang::QualType mapped_type =
224+
TryMapVoidPointer(context, type_id, wrapper_types);
208225
if (mapped_type.isNull()) {
209-
return mapped_type;
226+
mapped_type = MapNonWrapperType(context, inst_id, type_id);
227+
if (mapped_type.isNull()) {
228+
return mapped_type;
229+
}
210230
}
211231

212232
for (auto wrapper_type_id : llvm::reverse(wrapper_types)) {

toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
// CHECK:STDOUT: import_ir_insts: {}
2121
// CHECK:STDOUT: clang_decls: {}
2222
// CHECK:STDOUT: name_scopes:
23-
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000E, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
23+
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000F, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
2424
// CHECK:STDOUT: entity_names: {}
2525
// CHECK:STDOUT: cpp_global_vars: {}
2626
// CHECK:STDOUT: functions: {}
@@ -42,6 +42,7 @@
4242
// CHECK:STDOUT: 'inst(BoolType)': {kind: BoolType, type: type(TypeType)}
4343
// CHECK:STDOUT: 'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)}
4444
// CHECK:STDOUT: 'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)}
45+
// CHECK:STDOUT: 'inst(CustomCppVoidType)': {kind: CustomCppVoidType, type: type(TypeType)}
4546
// CHECK:STDOUT: 'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}
4647
// CHECK:STDOUT: 'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}
4748
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': {kind: ImplWitnessTablePlaceholder, type: type(TypeType)}
@@ -51,14 +52,15 @@
5152
// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}
5253
// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
5354
// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
54-
// CHECK:STDOUT: inst0000000E: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
55+
// CHECK:STDOUT: inst0000000F: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
5556
// CHECK:STDOUT: constant_values:
5657
// CHECK:STDOUT: values:
5758
// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType))
5859
// CHECK:STDOUT: 'inst(AutoType)': concrete_constant(inst(AutoType))
5960
// CHECK:STDOUT: 'inst(BoolType)': concrete_constant(inst(BoolType))
6061
// CHECK:STDOUT: 'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))
6162
// CHECK:STDOUT: 'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))
63+
// CHECK:STDOUT: 'inst(CustomCppVoidType)': concrete_constant(inst(CustomCppVoidType))
6264
// CHECK:STDOUT: 'inst(ErrorInst)': concrete_constant(inst(ErrorInst))
6365
// CHECK:STDOUT: 'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))
6466
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': concrete_constant(inst(ImplWitnessTablePlaceholder))
@@ -68,13 +70,13 @@
6870
// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))
6971
// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType))
7072
// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType))
71-
// CHECK:STDOUT: inst0000000E: concrete_constant(inst0000000E)
73+
// CHECK:STDOUT: inst0000000F: concrete_constant(inst0000000F)
7274
// CHECK:STDOUT: symbolic_constants: {}
7375
// CHECK:STDOUT: inst_blocks:
7476
// CHECK:STDOUT: inst_block_empty: {}
7577
// CHECK:STDOUT: exports: {}
7678
// CHECK:STDOUT: imports: {}
7779
// CHECK:STDOUT: global_init: {}
7880
// CHECK:STDOUT: inst_block60000004:
79-
// CHECK:STDOUT: 0: inst0000000E
81+
// CHECK:STDOUT: 0: inst0000000F
8082
// CHECK:STDOUT: ...

0 commit comments

Comments
 (0)