Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions toolchain/check/cpp/import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,9 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
context.ints().Add(ast_context.getTypeSize(qual_type))));
}
// TODO: Handle floating-point types that map to named aliases.
} else if (type.isVoidType()) {
return ExprAsType(context, Parse::NodeId::None,
SemIR::CppVoidType::TypeInstId);
}

return TypeExpr::None;
Expand Down Expand Up @@ -2116,6 +2119,7 @@ static auto LookupBuiltinTypes(Context& context, SemIR::LocId loc_id,
.Case("float", ast_context.FloatTy)
.Case("double", ast_context.DoubleTy)
.Case("long_double", ast_context.LongDoubleTy)
.Case("void", ast_context.VoidTy)
.Default(clang::QualType());
if (builtin_type.isNull()) {
return SemIR::InstId::None;
Expand Down
35 changes: 33 additions & 2 deletions toolchain/check/cpp/type_mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,33 @@ static auto MapNonWrapperType(Context& context, SemIR::InstId inst_id,
}
}

// Returns `void*` if the type is a wrapped `Cpp.void*`, consuming the pointer
// from `wrapper_types`. Otherwise returns no type.
static auto TryMapVoidPointer(Context& context, SemIR::TypeId type_id,
llvm::SmallVector<SemIR::TypeId>& wrapper_types)
-> clang::QualType {
if (type_id != SemIR::CppVoidType::TypeId || wrapper_types.empty()) {
return clang::QualType();
}

if (context.types().Is<SemIR::PointerType>(wrapper_types.back())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are probably other instructions that could be here which should be ignored, e.g. MaybeUnformedType. It might be worth thinking about whether a while loop here would be a good fit, but not asking for a change since wrapper_types doesn't support MaybeUnformedType right now either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this definitely makes sense to do when we can have a test that triggers this.

// `void*`.
wrapper_types.pop_back();
} else if (wrapper_types.size() >= 2 &&
context.types().Is<SemIR::ConstType>(wrapper_types.back()) &&
context.types().Is<SemIR::PointerType>(
wrapper_types[wrapper_types.size() - 2])) {
// `const void*`.
wrapper_types.erase(wrapper_types.end() - 2);
} else {
return clang::QualType();
}

return context.ast_context().getAttributedType(
clang::attr::TypeNonNull, context.ast_context().VoidPtrTy,
context.ast_context().VoidPtrTy);
}

// Maps a Carbon type to a C++ type. Accepts an InstId, representing a value
// whose type is mapped to a C++ type. Returns `clang::QualType` if the mapping
// succeeds, or `clang::QualType::isNull()` if the type is not supported.
Expand All @@ -219,9 +246,13 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
wrapper_types.push_back(orig_type_id);
}

clang::QualType mapped_type = MapNonWrapperType(context, inst_id, type_id);
clang::QualType mapped_type =
TryMapVoidPointer(context, type_id, wrapper_types);
if (mapped_type.isNull()) {
return mapped_type;
mapped_type = MapNonWrapperType(context, inst_id, type_id);
if (mapped_type.isNull()) {
return mapped_type;
}
}

for (auto wrapper_type_id : llvm::reverse(wrapper_types)) {
Expand Down
10 changes: 6 additions & 4 deletions toolchain/check/testdata/basics/raw_sem_ir/builtins.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// CHECK:STDOUT: import_ir_insts: {}
// CHECK:STDOUT: clang_decls: {}
// CHECK:STDOUT: name_scopes:
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000E, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
// CHECK:STDOUT: name_scope00000000: {inst: inst0000000F, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
// CHECK:STDOUT: entity_names: {}
// CHECK:STDOUT: cpp_global_vars: {}
// CHECK:STDOUT: functions: {}
Expand All @@ -42,6 +42,7 @@
// CHECK:STDOUT: 'inst(BoolType)': {kind: BoolType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(BoundMethodType)': {kind: BoundMethodType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(CharLiteralType)': {kind: CharLiteralType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(CppVoidType)': {kind: CppVoidType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}
// CHECK:STDOUT: 'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': {kind: ImplWitnessTablePlaceholder, type: type(TypeType)}
Expand All @@ -51,14 +52,15 @@
// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
// CHECK:STDOUT: inst0000000E: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
// CHECK:STDOUT: inst0000000F: {kind: Namespace, arg0: name_scope00000000, arg1: inst<none>, type: type(inst(NamespaceType))}
// CHECK:STDOUT: constant_values:
// CHECK:STDOUT: values:
// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType))
// CHECK:STDOUT: 'inst(AutoType)': concrete_constant(inst(AutoType))
// CHECK:STDOUT: 'inst(BoolType)': concrete_constant(inst(BoolType))
// CHECK:STDOUT: 'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))
// CHECK:STDOUT: 'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))
// CHECK:STDOUT: 'inst(CppVoidType)': concrete_constant(inst(CppVoidType))
// CHECK:STDOUT: 'inst(ErrorInst)': concrete_constant(inst(ErrorInst))
// CHECK:STDOUT: 'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))
// CHECK:STDOUT: 'inst(ImplWitnessTablePlaceholder)': concrete_constant(inst(ImplWitnessTablePlaceholder))
Expand All @@ -68,13 +70,13 @@
// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))
// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType))
// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType))
// CHECK:STDOUT: inst0000000E: concrete_constant(inst0000000E)
// CHECK:STDOUT: inst0000000F: concrete_constant(inst0000000F)
// CHECK:STDOUT: symbolic_constants: {}
// CHECK:STDOUT: inst_blocks:
// CHECK:STDOUT: inst_block_empty: {}
// CHECK:STDOUT: exports: {}
// CHECK:STDOUT: imports: {}
// CHECK:STDOUT: global_init: {}
// CHECK:STDOUT: inst_block60000004:
// CHECK:STDOUT: 0: inst0000000E
// CHECK:STDOUT: 0: inst0000000F
// CHECK:STDOUT: ...
Loading
Loading