Fix assertions and bad warnings on extremely wide bit-fields.

We used to produce a bogus warning if the width couldn't be represented
in 32 bits, and assert if it couldn't be represented in 64 bits.
This commit is contained in:
Richard Smith 2020-11-17 13:59:07 -08:00
parent a72f11ee20
commit 8e923ec2a8
3 changed files with 34 additions and 13 deletions

View File

@ -5649,9 +5649,8 @@ def err_incorrect_number_of_vector_initializers : Error<
def warn_bitfield_width_exceeds_type_width: Warning<
"width of bit-field %0 (%1 bits) exceeds the width of its type; value will "
"be truncated to %2 bit%s2">, InGroup<BitFieldWidth>;
def warn_anon_bitfield_width_exceeds_type_width : Warning<
"width of anonymous bit-field (%0 bits) exceeds width of its type; value "
"will be truncated to %1 bit%s1">, InGroup<BitFieldWidth>;
def err_bitfield_too_wide : Error<
"%select{bit-field %1|anonymous bit-field}0 is too wide (%2 bits)">;
def warn_bitfield_too_small_for_enum : Warning<
"bit-field %0 is not wide enough to store all enumerators of %1">,
InGroup<BitFieldEnumConversion>, DefaultIgnore;

View File

@ -16432,6 +16432,13 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
<< Value.toString(10);
}
// The size of the bit-field must not exceed our maximum permitted object
// size.
if (Value.getActiveBits() > ConstantArrayType::getMaxSizeBits(Context)) {
return Diag(FieldLoc, diag::err_bitfield_too_wide)
<< !FieldName << FieldName << Value.toString(10);
}
if (!FieldTy->isDependentType()) {
uint64_t TypeStorageSize = Context.getTypeSize(FieldTy);
uint64_t TypeWidth = Context.getIntWidth(FieldTy);
@ -16449,25 +16456,21 @@ ExprResult Sema::VerifyBitField(SourceLocation FieldLoc,
CStdConstraintViolation ? TypeWidth : TypeStorageSize;
if (FieldName)
return Diag(FieldLoc, diag::err_bitfield_width_exceeds_type_width)
<< FieldName << (unsigned)Value.getZExtValue()
<< FieldName << Value.toString(10)
<< !CStdConstraintViolation << DiagWidth;
return Diag(FieldLoc, diag::err_anon_bitfield_width_exceeds_type_width)
<< (unsigned)Value.getZExtValue() << !CStdConstraintViolation
<< Value.toString(10) << !CStdConstraintViolation
<< DiagWidth;
}
// Warn on types where the user might conceivably expect to get all
// specified bits as value bits: that's all integral types other than
// 'bool'.
if (BitfieldIsOverwide && !FieldTy->isBooleanType()) {
if (FieldName)
Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
<< FieldName << (unsigned)Value.getZExtValue()
<< (unsigned)TypeWidth;
else
Diag(FieldLoc, diag::warn_anon_bitfield_width_exceeds_type_width)
<< (unsigned)Value.getZExtValue() << (unsigned)TypeWidth;
if (BitfieldIsOverwide && !FieldTy->isBooleanType() && FieldName) {
Diag(FieldLoc, diag::warn_bitfield_width_exceeds_type_width)
<< FieldName << Value.toString(10)
<< (unsigned)TypeWidth;
}
}

View File

@ -10,6 +10,12 @@ struct Test1 {
CHECK_SIZE(Test1, 2);
CHECK_ALIGN(Test1, 1);
struct Test1a {
char : 9; // no warning (there's no value to truncate here)
};
CHECK_SIZE(Test1a, 2);
CHECK_ALIGN(Test1a, 1);
struct Test2 {
char c : 16; // expected-warning {{width of bit-field 'c' (16 bits) exceeds the width of its type; value will be truncated to 8 bits}}
};
@ -28,3 +34,16 @@ struct Test4 {
CHECK_SIZE(Test4, 8);
CHECK_ALIGN(Test4, 8);
struct Test5 {
char c : 0x100000001; // expected-warning {{width of bit-field 'c' (4294967297 bits) exceeds the width of its type; value will be truncated to 8 bits}}
};
// Size and align don't really matter here, just make sure we don't crash.
CHECK_SIZE(Test5, 1);
CHECK_ALIGN(Test5, 1);
struct Test6 {
char c : (unsigned __int128)0xffffffffffffffff + 2; // expected-error {{bit-field 'c' is too wide (18446744073709551617 bits)}}
};
// Size and align don't really matter here, just make sure we don't crash.
CHECK_SIZE(Test6, 1);
CHECK_ALIGN(Test6, 1);