From: Richard Trieu Date: Fri, 5 Aug 2016 02:39:30 +0000 (+0000) Subject: Allow -1 to assign max value to unsigned bitfields. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a9a97905f0cafad077280e1e49b35126fd3a3a7b;p=clang Allow -1 to assign max value to unsigned bitfields. Silence the -Wbitfield-constant-conversion warning for when -1 or other negative values are assigned to unsigned bitfields, provided that the bitfield is wider than the minimum number of bits needed to encode the negative value. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@277796 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index a534ead73d..c7163943cf 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -7827,6 +7827,12 @@ bool AnalyzeBitFieldAssignment(Sema &S, FieldDecl *Bitfield, Expr *Init, unsigned OriginalWidth = Value.getBitWidth(); unsigned FieldWidth = Bitfield->getBitWidthValue(S.Context); + if (Value.isSigned() && Value.isNegative()) + if (UnaryOperator *UO = dyn_cast(OriginalInit)) + if (UO->getOpcode() == UO_Minus) + if (isa(UO->getSubExpr())) + OriginalWidth = Value.getMinSignedBits(); + if (OriginalWidth <= FieldWidth) return false; diff --git a/test/Sema/bitfield.c b/test/Sema/bitfield.c index 810dc798ea..d625366e4e 100644 --- a/test/Sema/bitfield.c +++ b/test/Sema/bitfield.c @@ -64,7 +64,7 @@ typedef signed Signed; struct Test5 { unsigned n : 2; } t5; // Bitfield is unsigned -struct Test5 sometest5 = {-1}; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -1 to 3}} +struct Test5 sometest5 = {-1}; typedef __typeof__(+t5.n) Signed; // ... but promotes to signed. typedef __typeof__(t5.n + 0) Signed; // Arithmetic promotes. diff --git a/test/Sema/constant-conversion.c b/test/Sema/constant-conversion.c index b717f93253..203e737389 100644 --- a/test/Sema/constant-conversion.c +++ b/test/Sema/constant-conversion.c @@ -113,3 +113,15 @@ void test9() { char array_init[] = { 255, 127, 128, 129, 0 }; } + +void test10() { + struct S { + unsigned a : 4; + } s; + s.a = -1; + s.a = 15; + s.a = -8; + + s.a = -9; // expected-warning{{implicit truncation from 'int' to bitfield changes value from -9 to 7}} + s.a = 16; // expected-warning{{implicit truncation from 'int' to bitfield changes value from 16 to 0}} +}