docs/design/interoperability/literals.md
The behavior of literals that participate in interop depends on the direction of interop, but generally follows C++ rules:
1 becomes int according to C++ rules, and int maps to
i32 in Carbon.This is used:
Because there are no suffixes in Carbon for the integer types, a Carbon decimal integer literal will follow the C++ rules for decimal integers. Carbon also doesn't make a distinction between hexadecimal and binary literals for interop, so these literals will also follow the C++ rules for decimal integers without a suffix.
The first type from the following list in which the literal's value can fit is selected:
intlonglong long__int128If the value doesn’t fit in any of these types, the program is ill-formed and
diagnosed with an error. This matches the C++ standard behavior rather than
Clang's -Wimplicitly-unsigned-literal behavior.
Because decimal numbers are most commonly used as integer literals, this should match most existing C++ calls. To match a C++ call with a non-decimal literal argument expecting an unsigned type, an explicit unsigned type must be provided in Carbon. For example:
Cpp.f(0xDEADBEEF as u32);
As there are no suffixes in Carbon for the floating-point literals, a Carbon
floating-point literal will map to C++ double. If the value doesn’t fit in
double, the program is ill-formed.
A C++ integer literal will be given a C++ integer type following the C++ rules, which is then mapped to a Carbon type as defined in the primitive types mapping.
| C++ literal suffix | Carbon type with decimal C++ integer literals | Carbon type with hexadecimal, binary and octal C++ integer literals |
|---|---|---|
| (none) | Cpp.int, Cpp.long, Cpp.long_long | Cpp.int, Cpp.unsigned_int, Cpp.long, Cpp.unsigned_long, Cpp.long_long, Cpp.unsigned_long_long |
u or U | Cpp.unsigned_int, Cpp.unsigned_long, Cpp.unsigned_long_long | Cpp.unsigned_int, Cpp.unsigned_long, Cpp.unsigned_long_long |
l or L | Cpp.long, Cpp.long_long | Cpp.long, Cpp.unsigned_long, Cpp.long_long, Cpp.unsigned_long_long |
u or U and l or L | Cpp.unsigned_long, Cpp.unsigned_long_long | Cpp.unsigned_long, Cpp.unsigned_long_long |
ll or LL | Cpp.long_long | Cpp.long_long, Cpp.unsigned_long_long |
u or U and ll or LL | Cpp.unsigned_long_long | Cpp.unsigned_long_long |
z or Z (since C++23) | Cpp.uintptr_t | Cpp.uintptr_t, Cpp.size_t |
u or U and z or Z (since C++23) | Cpp.size_t | Cpp.size_t |
A C++ floating literal will be given a C++ type following the C++ rules, which is then mapped to a Carbon type as defined in primitive types mapping. :
| C++ floating-point literal suffix | Carbon floating-point literal type |
|---|---|
| (none) | f64 |
f or F | f32 |
l or L | Cpp.long_double |
f16 or F16 (since C++23) | f16 |
f32 or F32 (since C++23) | TBD |
f64 or F64 (since C++23) | TBD |
f128 or F128 (since C++23) | f128 |
bf16 or BF16 (since C++23) | TBD |
Carbon to C++ type mapping
C++ to Carbon type mapping