Author: Richard Smith Date: 2020-11-17T14:36:51-08:00 New Revision: 8e923ec2a803d54154aaa0079c1cfcf146b7a22f
URL: https://github.com/llvm/llvm-project/commit/8e923ec2a803d54154aaa0079c1cfcf146b7a22f DIFF: https://github.com/llvm/llvm-project/commit/8e923ec2a803d54154aaa0079c1cfcf146b7a22f.diff LOG: 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. Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDecl.cpp clang/test/SemaCXX/bitfield-layout.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index c47084c01367..2e479307ce22 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 19501f7f0d52..c78d37f70a04 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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; } } diff --git a/clang/test/SemaCXX/bitfield-layout.cpp b/clang/test/SemaCXX/bitfield-layout.cpp index 25aa82229925..7efd1d38c682 100644 --- a/clang/test/SemaCXX/bitfield-layout.cpp +++ b/clang/test/SemaCXX/bitfield-layout.cpp @@ -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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits