[clang] 8e923ec - Fix assertions and bad warnings on extremely wide bit-fields.
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 17 14:37:13 PST 2020
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);
More information about the cfe-commits
mailing list