2828
2929namespace Carbon ::Check {
3030
31- // Find the bit width of an integer literal.
32- // The default bit width is 32. If the literal's bit width is greater than 32,
33- // the bit width is increased to 64.
31+ // Find the bit width of an integer literal. Following the C++ standard rules
32+ // for assigning a type to a decimal integer literal, the first signed integer
33+ // in which the value could fit among bit widths of 32, 64 and 128 is selected.
34+ // If the value can't fit into a signed integer with width of 128-bits, then a
35+ // diagnostic is emitted and the function returns IntId::None. Returns
36+ // IntId::None also if the argument is not a constant integer, if it is an
37+ // error constant, or if it is a symbolic constant.
3438static auto FindIntLiteralBitWidth (Context& context, SemIR::InstId arg_id)
3539 -> IntId {
3640 auto arg_const_id = context.constant_values ().Get (arg_id);
@@ -42,13 +46,24 @@ static auto FindIntLiteralBitWidth(Context& context, SemIR::InstId arg_id)
4246 }
4347 auto arg = context.insts ().GetAs <SemIR::IntValue>(
4448 context.constant_values ().GetInstId (arg_const_id));
45- unsigned arg_non_sign_bits =
46- context. ints (). Get (arg. int_id ) .getSignificantBits () - 1 ;
49+ llvm::APInt arg_val = context. ints (). Get (arg. int_id );
50+ int arg_non_sign_bits = arg_val .getSignificantBits () - 1 ;
4751
48- // TODO: What if the literal is larger than 64 bits? Currently an error is
49- // reported that the int value is too large for type `i64`. Maybe try to fit
50- // in i128/i256? Try unsigned?
51- return (arg_non_sign_bits <= 32 ) ? IntId::MakeRaw (32 ) : IntId::MakeRaw (64 );
52+ if (arg_non_sign_bits >= 128 ) {
53+ CARBON_DIAGNOSTIC (IntTooLargeForCppType, Error,
54+ " integer value {0} too large to fit in a signed C++ "
55+ " integer type; requires {1} bits, but max is 128" ,
56+ TypedInt, int );
57+ context.emitter ().Emit (arg_id, IntTooLargeForCppType,
58+ {.type = arg.type_id , .value = arg_val},
59+ arg_non_sign_bits + 1 );
60+ return IntId::None;
61+ }
62+
63+ return (arg_non_sign_bits < 32 )
64+ ? IntId::MakeRaw (32 )
65+ : ((arg_non_sign_bits < 64 ) ? IntId::MakeRaw (64 )
66+ : IntId::MakeRaw (128 ));
5267}
5368
5469// Attempts to look up a type by name, and returns the corresponding `QualType`,
0 commit comments