Skip to content
Open
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
56 changes: 52 additions & 4 deletions core/prelude/types/cpp/int.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,80 @@ package Core library "prelude/types/cpp/int";
import library "prelude/operators";
import library "prelude/types/int";
import library "prelude/types/int_literal";
import library "prelude/types/uint";

namespace CppCompat;

// TODO: Add ULong32, LongLong64, ULongLong64.
class CppCompat.Long32 {
adapt i32;
}

class CppCompat.ULong32 {
adapt u32;
}

class CppCompat.LongLong64 {
adapt i64;
}

class CppCompat.ULongLong64 {
adapt u64;
}

// TODO: Copy.

// Conversions.

// TODO: ImplicitAs from IntLiteral to Long32.
// TODO: ImplicitAs from Long32 to IntLiteral.
// TODO: ImplicitAs from IntLiteral to Long32, ULong32, LongLong64, ULongLong64.
// TODO: ImplicitAs from Long32, ULong32, LongLong64, ULongLong64 to IntLiteral.

// TODO: ImplicitAs from Int(N) to Long32 if N < 32.
impl i32 as ImplicitAs(CppCompat.Long32) {
fn Convert[self: Self]() -> CppCompat.Long32 = "int.convert_checked";
}

// TODO: ImplicitAs from UInt(N) to ULong32 if N < 32.
impl u32 as ImplicitAs(CppCompat.ULong32) {
fn Convert[self: Self]() -> CppCompat.ULong32 = "int.convert_checked";
}

// TODO: ImplicitAs from Int(N) to LongLong64 if N < 64.
impl i64 as ImplicitAs(CppCompat.LongLong64) {
fn Convert[self: Self]() -> CppCompat.LongLong64 = "int.convert_checked";
}

// TODO: ImplicitAs from UInt(N) to ULongLong64 if N < 64.
impl u64 as ImplicitAs(CppCompat.ULongLong64) {
fn Convert[self: Self]() -> CppCompat.ULongLong64 = "int.convert_checked";
}

// TODO: ImplicitAs from Long32 to Int(N) if N > 32.
final impl CppCompat.Long32 as ImplicitAs(i32) {
fn Convert[self: Self]() -> i32 = "int.convert";
}

// TODO: ImplicitAs from ULong32 to UInt(N) if N > 32.
final impl CppCompat.ULong32 as ImplicitAs(u32) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Optional: I think I'd find it a little clearer to group the conversions for the same type together (e.g. group this together with u32 as ImplicitAs(CppCompat.ULong32)), rather than grouping the conversions by whether they're to or from a CppCompat type.

fn Convert[self: Self]() -> u32 = "int.convert";
}

// TODO: ImplicitAs from LongLong64 to Int(N) if N > 64.
final impl CppCompat.LongLong64 as ImplicitAs(i64) {
fn Convert[self: Self]() -> i64 = "int.convert";
}

// TODO: ImplicitAs from ULongLong64 to UInt(N) if N > 64.
final impl CppCompat.ULongLong64 as ImplicitAs(u64) {
fn Convert[self: Self]() -> u64 = "int.convert";
}

// TODO: As from Long32 to Int(N) if N < 32.
// TODO: As from ULong32 to UInt(N) if N < 32.
// TODO: As from LongLong64 to Int(N) if N < 64.
// TODO: As from ULongLong64 to UInt(N) if N < 64.
// TODO: As from Int(N) to Long32 if N > 32.
// TODO: As from UInt(N) to ULong32 if N > 32.
// TODO: As from Int(N) to LongLong64 if N > 64.
// TODO: As from UInt(N) to ULongLong64 if N > 64.

// TODO: Operations on Long32.
// TODO: Operations on Long32, ULong32, LongLong64, ULongLong64.
32 changes: 27 additions & 5 deletions toolchain/check/cpp/import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,21 @@ static auto MakeIntType(Context& context, IntId size_id, bool is_signed)
return ExprAsType(context, Parse::NodeId::None, type_inst_id);
}

// Maps a C++ builtin integer type to a Carbon `Core.CppCompat` type.
static auto MapBuiltinCppCompatIntegerType(Context& context,
unsigned int cpp_width,
unsigned int carbon_width,
llvm::StringRef cpp_compat_name)
-> TypeExpr {
if (cpp_width != carbon_width) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there cases where you expect this to happen, and it's not a bug in the toolchain?

return TypeExpr::None;
}

return ExprAsType(context, Parse::NodeId::None,
LookupNameInCore(context, Parse::NodeId::None,
{"CppCompat", cpp_compat_name}));
}

// Maps a C++ builtin integer type to a Carbon type.
// TODO: Handle integer types that map to named aliases.
static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
Expand All @@ -1112,11 +1127,18 @@ static auto MapBuiltinIntegerType(Context& context, SemIR::LocId loc_id,
return ExprAsType(context, Parse::NodeId::None,
MakeCharTypeLiteral(context, Parse::NodeId::None));
}
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy) &&
width == 32) {
return ExprAsType(context, Parse::NodeId::None,
LookupNameInCore(context, Parse::NodeId::None,
{"CppCompat", "Long32"}));
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongTy)) {
return MapBuiltinCppCompatIntegerType(context, width, 32, "Long32");
}
if (clang::ASTContext::hasSameType(qual_type, ast_context.UnsignedLongTy)) {
return MapBuiltinCppCompatIntegerType(context, width, 32, "ULong32");
}
if (clang::ASTContext::hasSameType(qual_type, ast_context.LongLongTy)) {
return MapBuiltinCppCompatIntegerType(context, width, 64, "LongLong64");
}
if (clang::ASTContext::hasSameType(qual_type,
ast_context.UnsignedLongLongTy)) {
return MapBuiltinCppCompatIntegerType(context, width, 64, "ULongLong64");
}
return TypeExpr::None;
}
Expand Down
26 changes: 22 additions & 4 deletions toolchain/check/cpp/type_mapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,17 @@ static auto LookupCppType(
: clang::QualType();
}

// Returns the given integer type if its width is as expected. Otherwise returns
// the null type.
static auto VerifyIntegerTypeWidth(Context& context, clang::QualType type,
unsigned int expected_width)
-> clang::QualType {
if (context.ast_context().getIntWidth(type) == expected_width) {
return type;
}
return clang::QualType();
}

// Maps a Carbon class type to a C++ type. Returns a null `QualType` if the
// type is not supported.
static auto TryMapClassType(Context& context, SemIR::ClassType class_type)
Expand Down Expand Up @@ -153,10 +164,17 @@ static auto TryMapClassType(Context& context, SemIR::ClassType class_type)
return ast_context.CharTy;
}
case SemIR::RecognizedTypeInfo::CppLong32: {
if (ast_context.getIntWidth(ast_context.LongTy) == 32) {
return ast_context.LongTy;
}
break;
return VerifyIntegerTypeWidth(context, ast_context.LongTy, 32);
}
case SemIR::RecognizedTypeInfo::CppULong32: {
return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongTy, 32);
}
case SemIR::RecognizedTypeInfo::CppLongLong64: {
return VerifyIntegerTypeWidth(context, ast_context.LongLongTy, 64);
}
case SemIR::RecognizedTypeInfo::CppULongLong64: {
return VerifyIntegerTypeWidth(context, ast_context.UnsignedLongLongTy,
64);
}
case SemIR::RecognizedTypeInfo::CppNullptrT: {
return ast_context.NullPtrTy;
Expand Down
Loading
Loading