Index: clang-tidy/hicpp/SignedBitwiseCheck.cpp =================================================================== --- clang-tidy/hicpp/SignedBitwiseCheck.cpp +++ clang-tidy/hicpp/SignedBitwiseCheck.cpp @@ -36,7 +36,8 @@ Finder->addMatcher( binaryOperator( allOf(anyOf(hasOperatorName("^"), hasOperatorName("|"), - hasOperatorName("&")), + hasOperatorName("&"), hasOperatorName("^="), + hasOperatorName("|="), hasOperatorName("&=")), unless(allOf(hasLHS(IsStdBitmask), hasRHS(IsStdBitmask))), @@ -48,10 +49,11 @@ // Shifting and complement is not allowed for any signed integer type because // the sign bit may corrupt the result. Finder->addMatcher( - binaryOperator(allOf(anyOf(hasOperatorName("<<"), hasOperatorName(">>")), - hasEitherOperand(SignedIntegerOperand), - hasLHS(hasType(isInteger())), - hasRHS(hasType(isInteger())))) + binaryOperator( + allOf(anyOf(hasOperatorName("<<"), hasOperatorName(">>"), + hasOperatorName("<<="), hasOperatorName(">>=")), + hasEitherOperand(SignedIntegerOperand), + hasLHS(hasType(isInteger())), hasRHS(hasType(isInteger())))) .bind("binary-sign-interference"), this); @@ -84,10 +86,8 @@ else llvm_unreachable("unexpected matcher result"); } - - diag(Location, - "use of a signed integer operand with a %select{binary|unary}0 bitwise " - "operator") + diag(Location, "use of a signed integer operand with a " + "%select{binary|unary}0 bitwise operator") << IsUnary << SignedOperand->getSourceRange(); } Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -156,6 +156,9 @@ ` added. +- Adding the missing bitwise assignment operations to + :doc:`hicpp-signed-bitwise `. + - The 'misc-forwarding-reference-overload' check was renamed to :doc:`bugprone-forwarding-reference-overload ` Index: test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp =================================================================== --- test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp +++ test/clang-tidy/hicpp-signed-bitwise-standard-types.cpp @@ -8,13 +8,19 @@ std::locale::category C = std::locale::category::ctype; SResult = std::locale::category::none | std::locale::category::collate; + SResult|= std::locale::category::collate; SResult = std::locale::category::ctype & std::locale::category::monetary; + SResult&= std::locale::category::monetary; SResult = std::locale::category::numeric ^ std::locale::category::time; + SResult^= std::locale::category::time; SResult = std::locale::category::messages | std::locale::category::all; SResult = std::locale::category::all & C; + SResult&= std::locale::category::all; SResult = std::locale::category::all | C; + SResult|= std::locale::category::all; SResult = std::locale::category::all ^ C; + SResult^= std::locale::category::all; // std::ctype_base::mask std::ctype_base::mask M = std::ctype_base::mask::punct; @@ -22,13 +28,13 @@ SResult = std::ctype_base::mask::space | std::ctype_base::mask::print; SResult = std::ctype_base::mask::cntrl & std::ctype_base::mask::upper; SResult = std::ctype_base::mask::lower ^ std::ctype_base::mask::alpha; - SResult = std::ctype_base::mask::digit | std::ctype_base::mask::punct; - SResult = std::ctype_base::mask::xdigit & std::ctype_base::mask::alnum; - SResult = std::ctype_base::mask::alnum ^ std::ctype_base::mask::graph; + SResult|= std::ctype_base::mask::digit | std::ctype_base::mask::punct; + SResult&= std::ctype_base::mask::xdigit & std::ctype_base::mask::alnum; + SResult^= std::ctype_base::mask::alnum ^ std::ctype_base::mask::graph; - SResult = std::ctype_base::mask::space & M; - SResult = std::ctype_base::mask::space | M; - SResult = std::ctype_base::mask::space ^ M; + SResult&= std::ctype_base::mask::space & M; + SResult|= std::ctype_base::mask::space | M; + SResult^= std::ctype_base::mask::space ^ M; // std::ios_base::fmtflags std::ios_base::fmtflags F = std::ios_base::fmtflags::floatfield; @@ -36,23 +42,23 @@ SResult = std::ios_base::fmtflags::dec | std::ios_base::fmtflags::oct; SResult = std::ios_base::fmtflags::hex & std::ios_base::fmtflags::basefield; SResult = std::ios_base::fmtflags::left ^ std::ios_base::fmtflags::right; - SResult = std::ios_base::fmtflags::internal | std::ios_base::fmtflags::adjustfield; - SResult = std::ios_base::fmtflags::scientific & std::ios_base::fmtflags::fixed; - SResult = std::ios_base::fmtflags::floatfield ^ std::ios_base::fmtflags::boolalpha; + SResult|= std::ios_base::fmtflags::internal | std::ios_base::fmtflags::adjustfield; + SResult&= std::ios_base::fmtflags::scientific & std::ios_base::fmtflags::fixed; + SResult^= std::ios_base::fmtflags::floatfield ^ std::ios_base::fmtflags::boolalpha; SResult = std::ios_base::fmtflags::showbase | std::ios_base::fmtflags::showpoint; SResult = std::ios_base::fmtflags::showpos & std::ios_base::fmtflags::skipws; SResult = std::ios_base::fmtflags::unitbuf ^ std::ios_base::fmtflags::uppercase; - SResult = std::ios_base::fmtflags::unitbuf | F; - SResult = std::ios_base::fmtflags::unitbuf & F; - SResult = std::ios_base::fmtflags::unitbuf ^ F; + SResult|= std::ios_base::fmtflags::unitbuf | F; + SResult&= std::ios_base::fmtflags::unitbuf & F; + SResult^= std::ios_base::fmtflags::unitbuf ^ F; // std::ios_base::iostate std::ios_base::iostate S = std::ios_base::iostate::goodbit; - SResult = std::ios_base::iostate::goodbit | std::ios_base::iostate::badbit; - SResult = std::ios_base::iostate::failbit & std::ios_base::iostate::eofbit; - SResult = std::ios_base::iostate::failbit ^ std::ios_base::iostate::eofbit; + SResult^= std::ios_base::iostate::goodbit | std::ios_base::iostate::badbit; + SResult|= std::ios_base::iostate::failbit & std::ios_base::iostate::eofbit; + SResult&= std::ios_base::iostate::failbit ^ std::ios_base::iostate::eofbit; SResult = std::ios_base::iostate::goodbit | S; SResult = std::ios_base::iostate::goodbit & S; @@ -65,9 +71,9 @@ SResult = std::ios_base::openmode::in & std::ios_base::openmode::out; SResult = std::ios_base::openmode::trunc ^ std::ios_base::openmode::ate; - SResult = std::ios_base::openmode::trunc | B; - SResult = std::ios_base::openmode::trunc & B; - SResult = std::ios_base::openmode::trunc ^ B; + SResult&= std::ios_base::openmode::trunc | B; + SResult^= std::ios_base::openmode::trunc & B; + SResult|= std::ios_base::openmode::trunc ^ B; } void still_forbidden() { @@ -83,13 +89,20 @@ // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator SResult = std::ctype_base::mask::lower ^ -8; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator + + // Staying within the allowed standard types is ok for bitwise assignment + // operations. + std::ctype_base::mask var = std::ctype_base::mask::print; + var<<= std::ctype_base::mask::upper; + var>>= std::ctype_base::mask::upper; + var &= std::ctype_base::mask::upper; + var |= std::ctype_base::mask::upper; + var ^= std::ctype_base::mask::upper; UResult = std::locale::category::collate << 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::locale::category::ctype << 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::locale::category::monetary >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::locale::category::numeric >> 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator @@ -109,11 +122,8 @@ UResult = std::ctype_base::mask::upper << 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ctype_base::mask::lower << 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ctype_base::mask::alpha >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ctype_base::mask::digit >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = ~std::ctype_base::mask::punct; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator @@ -131,11 +141,9 @@ UResult = std::ios_base::fmtflags::basefield >> 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::fmtflags::left >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::fmtflags::right << 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::fmtflags::internal << 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = ~std::ios_base::fmtflags::adjustfield; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator @@ -153,11 +161,9 @@ UResult = std::ios_base::iostate::eofbit << 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::iostate::goodbit << 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::iostate::badbit >> 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::iostate::failbit >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = ~std::ios_base::iostate::eofbit; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator @@ -175,11 +181,9 @@ UResult = std::ios_base::out >> 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::trunc >> 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::ate << 1; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = std::ios_base::ate << 1u; - // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = ~std::ios_base::openmode::app; // CHECK-MESSAGES: [[@LINE-1]]:13: warning: use of a signed integer operand with a unary bitwise operator Index: test/clang-tidy/hicpp-signed-bitwise.cpp =================================================================== --- test/clang-tidy/hicpp-signed-bitwise.cpp +++ test/clang-tidy/hicpp-signed-bitwise.cpp @@ -41,9 +41,12 @@ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator UResult = SValue & -1; // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use of a signed integer operand with a binary bitwise operator + UResult&= 1; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator UResult = UValue & 1u; // Ok UResult = UValue & UValue; // Ok + UResult&= 2u; // Ok unsigned char UByte1 = 0u; unsigned char UByte2 = 16u; @@ -68,18 +71,30 @@ UByte1 = UByte1 | UByte2; // Ok UByte1 = UByte1 | SByte2; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator + UByte1|= SByte2; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator + UByte1|= UByte2; // Ok UByte1 = UByte1 ^ UByte2; // Ok UByte1 = UByte1 ^ SByte2; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator + UByte1^= SByte2; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator + UByte1^= UByte2; // Ok UByte1 = UByte1 >> UByte2; // Ok UByte1 = UByte1 >> SByte2; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator + UByte1>>= SByte2; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator + UByte1>>= UByte2; // Ok UByte1 = UByte1 << UByte2; // Ok UByte1 = UByte1 << SByte2; // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use of a signed integer operand with a binary bitwise operator + UByte1<<= SByte2; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator + UByte1<<= UByte2; // Ok int SignedInt1 = 1 << 12; // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use of a signed integer operand with a binary bitwise operator @@ -195,10 +210,16 @@ int s3; s3 = IntOne | IntTwo; // Signed // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator + s3|= IntTwo; // Signed + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator s3 = IntOne & IntTwo; // Signed // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator + s3&= IntTwo; // Signed + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator s3 = IntOne ^ IntTwo; // Signed // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator + s3^= IntTwo; // Signed + // CHECK-MESSAGES: [[@LINE-1]]:3: warning: use of a signed integer operand with a binary bitwise operator s3 = s1 | s2; // Signed // CHECK-MESSAGES: [[@LINE-1]]:8: warning: use of a signed integer operand with a binary bitwise operator s3 = s1 & s2; // Signed