Skip to content

Commit bef92cf

Browse files
authored
Add CppCompat.ULong32, CppCompat.LongLong64 and CppCompat.ULongLong64 (carbon-language#6386)
This extends carbon-language#6364 to allow having: * `Cpp.unsigned_long` as a distinct type when `unsigned long` is 32 bits. * `Cpp.long_long` and `Cpp.unsigned_long_long` as distinct types when `long` and `unsigned long` are 64 bits. Similarly to carbon-language#6364, we only support implicit conversions from the matching literal type (`u32`, `i64` and `u64`). See carbon-language#6275 for rationale. Part of carbon-language#5263.
1 parent 05fd656 commit bef92cf

File tree

10 files changed

+1291
-423
lines changed

10 files changed

+1291
-423
lines changed

core/prelude/types/cpp/int.carbon

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,32 @@ package Core library "prelude/types/cpp/int";
77
import library "prelude/operators";
88
import library "prelude/types/int";
99
import library "prelude/types/int_literal";
10+
import library "prelude/types/uint";
1011

1112
namespace CppCompat;
1213

13-
// TODO: Add ULong32, LongLong64, ULongLong64.
1414
class CppCompat.Long32 {
1515
adapt i32;
1616
}
1717

18+
class CppCompat.ULong32 {
19+
adapt u32;
20+
}
21+
22+
class CppCompat.LongLong64 {
23+
adapt i64;
24+
}
25+
26+
class CppCompat.ULongLong64 {
27+
adapt u64;
28+
}
29+
1830
// TODO: Copy.
1931

2032
// Conversions.
2133

22-
// TODO: ImplicitAs from IntLiteral to Long32.
23-
// TODO: ImplicitAs from Long32 to IntLiteral.
34+
// TODO: ImplicitAs from IntLiteral to Long32, ULong32, LongLong64, ULongLong64.
35+
// TODO: ImplicitAs from Long32, ULong32, LongLong64, ULongLong64 to IntLiteral.
2436

2537
// TODO: ImplicitAs from Int(N) to Long32 if N < 32.
2638
impl i32 as ImplicitAs(CppCompat.Long32) {
@@ -32,7 +44,43 @@ final impl CppCompat.Long32 as ImplicitAs(i32) {
3244
fn Convert[self: Self]() -> i32 = "int.convert";
3345
}
3446

47+
// TODO: ImplicitAs from UInt(N) to ULong32 if N < 32.
48+
impl u32 as ImplicitAs(CppCompat.ULong32) {
49+
fn Convert[self: Self]() -> CppCompat.ULong32 = "int.convert_checked";
50+
}
51+
52+
// TODO: ImplicitAs from ULong32 to UInt(N) if N > 32.
53+
final impl CppCompat.ULong32 as ImplicitAs(u32) {
54+
fn Convert[self: Self]() -> u32 = "int.convert";
55+
}
56+
57+
// TODO: ImplicitAs from Int(N) to LongLong64 if N < 64.
58+
impl i64 as ImplicitAs(CppCompat.LongLong64) {
59+
fn Convert[self: Self]() -> CppCompat.LongLong64 = "int.convert_checked";
60+
}
61+
62+
// TODO: ImplicitAs from LongLong64 to Int(N) if N > 64.
63+
final impl CppCompat.LongLong64 as ImplicitAs(i64) {
64+
fn Convert[self: Self]() -> i64 = "int.convert";
65+
}
66+
67+
// TODO: ImplicitAs from UInt(N) to ULongLong64 if N < 64.
68+
impl u64 as ImplicitAs(CppCompat.ULongLong64) {
69+
fn Convert[self: Self]() -> CppCompat.ULongLong64 = "int.convert_checked";
70+
}
71+
72+
// TODO: ImplicitAs from ULongLong64 to UInt(N) if N > 64.
73+
final impl CppCompat.ULongLong64 as ImplicitAs(u64) {
74+
fn Convert[self: Self]() -> u64 = "int.convert";
75+
}
76+
3577
// TODO: As from Long32 to Int(N) if N < 32.
78+
// TODO: As from ULong32 to UInt(N) if N < 32.
79+
// TODO: As from LongLong64 to Int(N) if N < 64.
80+
// TODO: As from ULongLong64 to UInt(N) if N < 64.
3681
// TODO: As from Int(N) to Long32 if N > 32.
82+
// TODO: As from UInt(N) to ULong32 if N > 32.
83+
// TODO: As from Int(N) to LongLong64 if N > 64.
84+
// TODO: As from UInt(N) to ULongLong64 if N > 64.
3785

38-
// TODO: Operations on Long32.
86+
// TODO: Operations on Long32, ULong32, LongLong64, ULongLong64.

toolchain/check/cpp/import.cpp

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,19 @@ static auto MakeCppCompatType(Context& context, SemIR::LocId loc_id,
10881088
LookupNameInCore(context, loc_id, {"CppCompat", name}));
10891089
}
10901090

1091+
// Maps a C++ builtin integer type to a Carbon `Core.CppCompat` type.
1092+
static auto MapBuiltinCppCompatIntegerType(Context& context,
1093+
unsigned int cpp_width,
1094+
unsigned int carbon_width,
1095+
llvm::StringRef cpp_compat_name)
1096+
-> TypeExpr {
1097+
if (cpp_width != carbon_width) {
1098+
return TypeExpr::None;
1099+
}
1100+
1101+
return MakeCppCompatType(context, Parse::NodeId::None, cpp_compat_name);
1102+
}
1103+
10911104
// Maps a C++ builtin integer type to a Carbon type.
10921105
// TODO: Handle integer types that map to named aliases.
10931106
static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
@@ -1114,9 +1127,18 @@ static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
11141127
return ExprAsType(context, Parse::NodeId::None,
11151128
MakeCharTypeLiteral(context, Parse::NodeId::None));
11161129
}
1117-
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy) &&
1118-
width == 32) {
1119-
return MakeCppCompatType(context, loc_id, "Long32");
1130+
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy)) {
1131+
return MapBuiltinCppCompatIntegerType(context, width, 32, "Long32");
1132+
}
1133+
if (clang::ASTContext::hasSameType(qual_type, ast_context.UnsignedLongTy)) {
1134+
return MapBuiltinCppCompatIntegerType(context, width, 32, "ULong32");
1135+
}
1136+
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongLongTy)) {
1137+
return MapBuiltinCppCompatIntegerType(context, width, 64, "LongLong64");
1138+
}
1139+
if (clang::ASTContext::hasSameType(qual_type,
1140+
ast_context.UnsignedLongLongTy)) {
1141+
return MapBuiltinCppCompatIntegerType(context, width, 64, "ULongLong64");
11201142
}
11211143
return TypeExpr::None;
11221144
}

toolchain/check/cpp/type_mapping.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@ static auto LookupCppType(
122122
: clang::QualType();
123123
}
124124

125+
// Returns the given integer type if its width is as expected. Otherwise returns
126+
// the null type.
127+
static auto VerifyIntegerTypeWidth(Context& context, clang::QualType type,
128+
unsigned int expected_width)
129+
-> clang::QualType {
130+
if (context.ast_context().getIntWidth(type) == expected_width) {
131+
return type;
132+
}
133+
return clang::QualType();
134+
}
135+
125136
// Maps a Carbon class type to a C++ type. Returns a null `QualType` if the
126137
// type is not supported.
127138
static auto TryMapClassType(Context& context, SemIR::ClassType class_type)
@@ -175,10 +186,17 @@ static auto TryMapClassType(Context& context, SemIR::ClassType class_type)
175186
return ast_context.CharTy;
176187
}
177188
case SemIR::RecognizedTypeInfo::CppLong32: {
178-
if (ast_context.getIntWidth(ast_context.LongTy) == 32) {
179-
return ast_context.LongTy;
180-
}
181-
break;
189+
return VerifyIntegerTypeWidth(context, ast_context.LongTy, 32);
190+
}
191+
case SemIR::RecognizedTypeInfo::CppULong32: {
192+
return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongTy, 32);
193+
}
194+
case SemIR::RecognizedTypeInfo::CppLongLong64: {
195+
return VerifyIntegerTypeWidth(context, ast_context.LongLongTy, 64);
196+
}
197+
case SemIR::RecognizedTypeInfo::CppULongLong64: {
198+
return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongLongTy,
199+
64);
182200
}
183201
case SemIR::RecognizedTypeInfo::CppNullptrT: {
184202
return ast_context.NullPtrTy;

0 commit comments

Comments
 (0)