diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2012-01-26 23:11:39 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2012-01-26 23:11:39 +0000 |
commit | 3a643afa402d51b5fc4faccb4329e9c4392d4551 (patch) | |
tree | 7fac73e67973f5a554d9768204d7f9e9110e7b8e | |
parent | 1bd91374498ac78e72545f08f4daa6491f9c9d14 (diff) |
Make the bitfield implicit truncation warning slightly more aggressive, and make the printed warning a bit more accurate. The new behavior matches gcc's -Wconversion. <rdar://problem/10238797>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149089 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 17 | ||||
-rw-r--r-- | test/Sema/constant-conversion.c | 14 |
2 files changed, 21 insertions, 10 deletions
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 950a575891..8d01352fd2 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -3655,19 +3655,20 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, if (OriginalWidth <= FieldWidth) return false; + // Compute the value which the bitfield will contain. llvm::APSInt TruncatedValue = Value.trunc(FieldWidth); + TruncatedValue.setIsSigned(Bitfield->getType()->isSignedIntegerType()); - // It's fairly common to write values into signed bitfields - // that, if sign-extended, would end up becoming a different - // value. We don't want to warn about that. - if (Value.isSigned() && Value.isNegative()) - TruncatedValue = TruncatedValue.sext(OriginalWidth); - else - TruncatedValue = TruncatedValue.zext(OriginalWidth); - + // Check whether the stored value is equal to the original value. + TruncatedValue = TruncatedValue.extend(OriginalWidth); if (Value == TruncatedValue) return false; + // Special-case bitfields of width 1: booleans are naturally 0/1, and + // therefore don't strictly fit into a bitfield of width 1. + if (FieldWidth == 1 && Value.getBoolValue() == TruncatedValue.getBoolValue()) + return false; + std::string PrettyValue = Value.toString(10); std::string PrettyTrunc = TruncatedValue.toString(10); diff --git a/test/Sema/constant-conversion.c b/test/Sema/constant-conversion.c index a2c48d3549..c97eb05cd1 100644 --- a/test/Sema/constant-conversion.c +++ b/test/Sema/constant-conversion.c @@ -31,8 +31,8 @@ void test3() { int bar : 2; }; - struct A a = { 0, 10 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} - struct A b[] = { 0, 10, 0, 0 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} + struct A a = { 0, 10 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to -2}} + struct A b[] = { 0, 10, 0, 0 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to -2}} struct A c[] = {{10, 0}}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} struct A d = (struct A) { 10, 0 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} struct A e = { .foo = 10 }; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 10 to 2}} @@ -62,3 +62,13 @@ void test6() { unsigned char y = 1 ? 65535 : 1; // expected-warning {{changes value}} } +void test7() { + struct { + unsigned int twoBits1:2; + unsigned int twoBits2:2; + unsigned int reserved:28; + } f; + + f.twoBits1 = ~1; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -2 to 2}} + f.twoBits2 = ~2; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -3 to 1}} +} |