Skip to content

Commit 0678501

Browse files
authored
Replace builtin CppVoidType with a prelude type. (#6403)
Following #6357, map C++ `void` to a prelude class type `Core.CppCompat.VoidBase`, not to a builtin type. This is mostly just moving logic around, but does notably change `Cpp.void` from being an incomplete type to being a complete-but-abstract type. Also change `NullptrT` to be an adapter for `void*` instead of `()*`, to follow the approved design. Implicit conversions to `void` and to `void*` are still absent. Part of #6280.
1 parent da8c9d6 commit 0678501

29 files changed

+2427
-2253
lines changed

core/prelude/types.carbon

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ package Core library "prelude/types";
77
export import library "prelude/types/bool";
88
export import library "prelude/types/char";
99
export import library "prelude/types/cpp/int";
10+
export import library "prelude/types/cpp/nullptr";
11+
export import library "prelude/types/cpp/void";
1012
export import library "prelude/types/float";
1113
export import library "prelude/types/float_literal";
1214
export import library "prelude/types/int";
1315
export import library "prelude/types/int_literal";
1416
export import library "prelude/types/maybe_unformed";
15-
export import library "prelude/types/cpp/nullptr";
1617
export import library "prelude/types/optional";
1718
export import library "prelude/types/string";
1819
export import library "prelude/types/uint";

core/prelude/types/cpp/nullptr.carbon

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ package Core library "prelude/types/cpp/nullptr";
77
import library "prelude/copy";
88
import library "prelude/destroy";
99
import library "prelude/operators/as";
10-
import library "prelude/types/optional";
10+
import library "prelude/types/cpp/void";
1111
import library "prelude/types/maybe_unformed";
12+
import library "prelude/types/optional";
1213

1314
namespace CppCompat;
1415

@@ -26,7 +27,7 @@ class CppCompat.NullptrT {
2627
// nullptr_t has the same size and alignment as a pointer, but the
2728
// corresponding pointer is always unformed.
2829
// TODO: Give this type a custom empty value representation.
29-
adapt MaybeUnformed(()*);
30+
adapt MaybeUnformed(VoidBase*);
3031

3132
fn Make() -> Self {
3233
returned var s: Self;

core/prelude/types/cpp/void.carbon

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
// Exceptions. See /LICENSE for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
package Core library "prelude/types/cpp/void";
6+
7+
namespace CppCompat;
8+
9+
// C++ `void` as a Carbon type.
10+
//
11+
// This type represents a notional "base-most" object at the root of every
12+
// inheritance hierarchy. There are no objects of type `VoidType`, but any value
13+
// can be converted to a value of type `VoidType`.
14+
//
15+
// This type is used as the default mapping for C++ `void`, which is used in
16+
// most contexts in which `void` can appear: for example, as a pointee of a
17+
// pointer type, as the type of a typedef, or as a type template argument.
18+
// However, in a function signature, a `void` return type maps to `()` instead,
19+
// and a `(void)` parameter list maps to `()`.
20+
//
21+
// This type is also available via the alias `Cpp.void`.
22+
abstract class CppCompat.VoidBase {
23+
adapt ();
24+
}
25+
26+
// TODO: An unqualified pointer to `T` should implicitly convert to a pointer to
27+
// `<qualifiers> void` if `<qualifiers>` includes all of the qualifiers for `T`.
28+
// Similarly, a value of type `T` should implicitly convert to a value of type
29+
// `void`.

toolchain/check/cpp/import.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,12 @@ static auto MakeIntType(Context& context, IntId size_id, bool is_signed)
10621062
return ExprAsType(context, Parse::NodeId::None, type_inst_id);
10631063
}
10641064

1065+
static auto MakeCppCompatType(Context& context, SemIR::LocId loc_id,
1066+
llvm::StringRef name) -> TypeExpr {
1067+
return ExprAsType(context, loc_id,
1068+
LookupNameInCore(context, loc_id, {"CppCompat", name}));
1069+
}
1070+
10651071
// Maps a C++ builtin integer type to a Carbon type.
10661072
// TODO: Handle integer types that map to named aliases.
10671073
static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
@@ -1090,17 +1096,13 @@ static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
10901096
}
10911097
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy) &&
10921098
width == 32) {
1093-
return ExprAsType(context, Parse::NodeId::None,
1094-
LookupNameInCore(context, Parse::NodeId::None,
1095-
{"CppCompat", "Long32"}));
1099+
return MakeCppCompatType(context, loc_id, "Long32");
10961100
}
10971101
return TypeExpr::None;
10981102
}
10991103

11001104
static auto MapNullptrType(Context& context, SemIR::LocId loc_id) -> TypeExpr {
1101-
return ExprAsType(
1102-
context, loc_id,
1103-
LookupNameInCore(context, loc_id, {"CppCompat", "NullptrT"}));
1105+
return MakeCppCompatType(context, loc_id, "NullptrT");
11041106
}
11051107

11061108
// Maps a C++ builtin type to a Carbon type.
@@ -1129,8 +1131,7 @@ static auto MapBuiltinType(Context& context, SemIR::LocId loc_id,
11291131
}
11301132
// TODO: Handle floating-point types that map to named aliases.
11311133
} else if (type.isVoidType()) {
1132-
return ExprAsType(context, Parse::NodeId::None,
1133-
SemIR::CppVoidType::TypeInstId);
1134+
return MakeCppCompatType(context, loc_id, "VoidBase");
11341135
} else if (type.isNullPtrType()) {
11351136
return MapNullptrType(context, loc_id);
11361137
}

toolchain/check/cpp/type_mapping.cpp

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ static auto TryMapClassType(Context& context, SemIR::ClassType class_type)
161161
case SemIR::RecognizedTypeInfo::CppNullptrT: {
162162
return ast_context.NullPtrTy;
163163
}
164+
case SemIR::RecognizedTypeInfo::CppVoidBase: {
165+
return ast_context.VoidTy;
166+
}
164167
case SemIR::RecognizedTypeInfo::Str: {
165168
return LookupCppType(context, {"std", "string_view"});
166169
}
@@ -207,33 +210,6 @@ static auto MapNonWrapperType(Context& context, SemIR::InstId inst_id,
207210
}
208211
}
209212

210-
// Returns `void*` if the type is a wrapped `Cpp.void*`, consuming the pointer
211-
// from `wrapper_types`. Otherwise returns no type.
212-
static auto TryMapVoidPointer(Context& context, SemIR::TypeId type_id,
213-
llvm::SmallVector<SemIR::TypeId>& wrapper_types)
214-
-> clang::QualType {
215-
if (type_id != SemIR::CppVoidType::TypeId || wrapper_types.empty()) {
216-
return clang::QualType();
217-
}
218-
219-
if (context.types().Is<SemIR::PointerType>(wrapper_types.back())) {
220-
// `void*`.
221-
wrapper_types.pop_back();
222-
} else if (wrapper_types.size() >= 2 &&
223-
context.types().Is<SemIR::ConstType>(wrapper_types.back()) &&
224-
context.types().Is<SemIR::PointerType>(
225-
wrapper_types[wrapper_types.size() - 2])) {
226-
// `const void*`.
227-
wrapper_types.erase(wrapper_types.end() - 2);
228-
} else {
229-
return clang::QualType();
230-
}
231-
232-
return context.ast_context().getAttributedType(
233-
clang::attr::TypeNonNull, context.ast_context().VoidPtrTy,
234-
context.ast_context().VoidPtrTy);
235-
}
236-
237213
// Maps a Carbon type to a C++ type. Accepts an InstId, representing a value
238214
// whose type is mapped to a C++ type. Returns `clang::QualType` if the mapping
239215
// succeeds, or `clang::QualType::isNull()` if the type is not supported.
@@ -258,13 +234,9 @@ static auto MapToCppType(Context& context, SemIR::InstId inst_id)
258234
wrapper_types.push_back(orig_type_id);
259235
}
260236

261-
clang::QualType mapped_type =
262-
TryMapVoidPointer(context, type_id, wrapper_types);
237+
clang::QualType mapped_type = MapNonWrapperType(context, inst_id, type_id);
263238
if (mapped_type.isNull()) {
264-
mapped_type = MapNonWrapperType(context, inst_id, type_id);
265-
if (mapped_type.isNull()) {
266-
return mapped_type;
267-
}
239+
return mapped_type;
268240
}
269241

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

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

Lines changed: 4 additions & 6 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_scope0: {inst: instE, parent_scope: name_scope<none>, has_error: false, extended_scopes: [], names: {}}
23+
// CHECK:STDOUT: name_scope0: {inst: instD, 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,7 +42,6 @@
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(CppVoidType)': {kind: CppVoidType, type: type(TypeType)}
4645
// CHECK:STDOUT: 'inst(ErrorInst)': {kind: ErrorInst, type: type(Error)}
4746
// CHECK:STDOUT: 'inst(FloatLiteralType)': {kind: FloatLiteralType, type: type(TypeType)}
4847
// CHECK:STDOUT: 'inst(InstType)': {kind: InstType, type: type(TypeType)}
@@ -51,15 +50,14 @@
5150
// CHECK:STDOUT: 'inst(SpecificFunctionType)': {kind: SpecificFunctionType, type: type(TypeType)}
5251
// CHECK:STDOUT: 'inst(VtableType)': {kind: VtableType, type: type(TypeType)}
5352
// CHECK:STDOUT: 'inst(WitnessType)': {kind: WitnessType, type: type(TypeType)}
54-
// CHECK:STDOUT: instE: {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
53+
// CHECK:STDOUT: instD: {kind: Namespace, arg0: name_scope0, arg1: inst<none>, type: type(inst(NamespaceType))}
5554
// CHECK:STDOUT: constant_values:
5655
// CHECK:STDOUT: values:
5756
// CHECK:STDOUT: 'inst(TypeType)': concrete_constant(inst(TypeType))
5857
// CHECK:STDOUT: 'inst(AutoType)': concrete_constant(inst(AutoType))
5958
// CHECK:STDOUT: 'inst(BoolType)': concrete_constant(inst(BoolType))
6059
// CHECK:STDOUT: 'inst(BoundMethodType)': concrete_constant(inst(BoundMethodType))
6160
// CHECK:STDOUT: 'inst(CharLiteralType)': concrete_constant(inst(CharLiteralType))
62-
// CHECK:STDOUT: 'inst(CppVoidType)': concrete_constant(inst(CppVoidType))
6361
// CHECK:STDOUT: 'inst(ErrorInst)': concrete_constant(inst(ErrorInst))
6462
// CHECK:STDOUT: 'inst(FloatLiteralType)': concrete_constant(inst(FloatLiteralType))
6563
// CHECK:STDOUT: 'inst(InstType)': concrete_constant(inst(InstType))
@@ -68,13 +66,13 @@
6866
// CHECK:STDOUT: 'inst(SpecificFunctionType)': concrete_constant(inst(SpecificFunctionType))
6967
// CHECK:STDOUT: 'inst(VtableType)': concrete_constant(inst(VtableType))
7068
// CHECK:STDOUT: 'inst(WitnessType)': concrete_constant(inst(WitnessType))
71-
// CHECK:STDOUT: instE: concrete_constant(instE)
69+
// CHECK:STDOUT: instD: concrete_constant(instD)
7270
// CHECK:STDOUT: symbolic_constants: {}
7371
// CHECK:STDOUT: inst_blocks:
7472
// CHECK:STDOUT: inst_block_empty: {}
7573
// CHECK:STDOUT: exports: {}
7674
// CHECK:STDOUT: imports: {}
7775
// CHECK:STDOUT: global_init: {}
7876
// CHECK:STDOUT: inst_block60000004:
79-
// CHECK:STDOUT: 0: instE
77+
// CHECK:STDOUT: 0: instD
8078
// CHECK:STDOUT: ...

0 commit comments

Comments
 (0)