1313#include < optional>
1414#include < utility>
1515
16- // TODO: change warning message
17-
1816using namespace clang ::ast_matchers;
1917
2018namespace clang ::tidy::misc {
@@ -86,37 +84,48 @@ static llvm::StringRef translate(llvm::StringRef Value) {
8684 return {};
8785}
8886
89- static bool isBooleanBitwise (const BinaryOperator *BinOp, ASTContext *AC, std::optional<bool >& rootAssignsToBoolean) {
87+ static bool isBooleanBitwise (const BinaryOperator *BinOp, ASTContext *AC,
88+ std::optional<bool > &rootAssignsToBoolean) {
9089 if (!BinOp)
9190 return false ;
9291
9392 for (const auto &[Bitwise, _] : OperatorsTransformation) {
9493 if (BinOp->getOpcodeStr () == Bitwise) {
95- const bool lhsBoolean = BinOp->getLHS ()
96- ->IgnoreImpCasts ()
97- ->getType ()
98- .getDesugaredType (*AC)
99- ->isBooleanType ();
100- const bool rhsBoolean = BinOp->getRHS ()
101- ->IgnoreImpCasts ()
102- ->getType ()
103- .getDesugaredType (*AC)
104- ->isBooleanType ();
105- if (lhsBoolean && rhsBoolean) {
106- rootAssignsToBoolean = rootAssignsToBoolean.value_or (false );
107- return true ;
108- }
109- if (assignsToBoolean (BinOp, AC) || rootAssignsToBoolean.value_or (false )) {
110- rootAssignsToBoolean = rootAssignsToBoolean.value_or (true );
111- return true ;
112- }
113- if (BinOp->isCompoundAssignmentOp () && lhsBoolean) {
114- rootAssignsToBoolean = rootAssignsToBoolean.value_or (true );
115- return true ;
116- }
117- if (std::optional<bool > DummyFlag = false ; (lhsBoolean || isBooleanBitwise (dyn_cast<BinaryOperator>(BinOp->getLHS ()->IgnoreParenImpCasts ()), AC, DummyFlag)) && (rhsBoolean || isBooleanBitwise (dyn_cast<BinaryOperator>(BinOp->getRHS ()->IgnoreParenImpCasts ()), AC, DummyFlag))) {
118- rootAssignsToBoolean = rootAssignsToBoolean.value_or (false );
119- return true ;
94+ bool lhsBoolean = BinOp->getLHS ()
95+ ->IgnoreImpCasts ()
96+ ->getType ()
97+ .getDesugaredType (*AC)
98+ ->isBooleanType ();
99+ bool rhsBoolean = BinOp->getRHS ()
100+ ->IgnoreImpCasts ()
101+ ->getType ()
102+ .getDesugaredType (*AC)
103+ ->isBooleanType ();
104+ for (int i = 0 ; i < 2 ; ++i) {
105+ if (lhsBoolean && rhsBoolean) {
106+ rootAssignsToBoolean = rootAssignsToBoolean.value_or (false );
107+ return true ;
108+ }
109+ if (assignsToBoolean (BinOp, AC) ||
110+ rootAssignsToBoolean.value_or (false )) {
111+ rootAssignsToBoolean = rootAssignsToBoolean.value_or (true );
112+ return true ;
113+ }
114+ if (BinOp->isCompoundAssignmentOp () && lhsBoolean) {
115+ rootAssignsToBoolean = rootAssignsToBoolean.value_or (true );
116+ return true ;
117+ }
118+ std::optional<bool > DummyFlag = false ;
119+ lhsBoolean =
120+ lhsBoolean ||
121+ isBooleanBitwise (dyn_cast<BinaryOperator>(
122+ BinOp->getLHS ()->IgnoreParenImpCasts ()),
123+ AC, DummyFlag);
124+ rhsBoolean =
125+ rhsBoolean ||
126+ isBooleanBitwise (dyn_cast<BinaryOperator>(
127+ BinOp->getRHS ()->IgnoreParenImpCasts ()),
128+ AC, DummyFlag);
120129 }
121130 }
122131 }
@@ -151,14 +160,17 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
151160 const NamedDecl *ND = getLHSNamedDeclIfCompoundAssign (BinOp);
152161 return diag (BinOp->getOperatorLoc (),
153162 " use logical operator '%0' for boolean %select{variable "
154- " %2|values }1 instead of bitwise operator '%3'" )
163+ " %2|semantics }1 instead of bitwise operator '%3'" )
155164 << translate (BinOp->getOpcodeStr ()) << (ND == nullptr ) << ND
156165 << BinOp->getOpcodeStr ();
157166 };
158167
159168 const bool HasVolatileOperand = llvm::any_of (
160169 std::array{BinOp->getLHS (), BinOp->getRHS ()}, [&](const Expr *E) {
161- return E->IgnoreImpCasts ()->getType ().getDesugaredType (Ctx).isVolatileQualified ();
170+ return E->IgnoreImpCasts ()
171+ ->getType ()
172+ .getDesugaredType (Ctx)
173+ .isVolatileQualified ();
162174 });
163175 if (HasVolatileOperand)
164176 return static_cast <void >(DiagEmitter ());
@@ -250,8 +262,7 @@ void BoolBitwiseOperationCheck::emitWarningAndChangeOperatorsIfPossible(
250262void BoolBitwiseOperationCheck::visitBinaryTreesNode (
251263 const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
252264 const clang::SourceManager &SM, clang::ASTContext &Ctx,
253- std::optional<bool >& rootAssignsToBoolean) {
254- // llvm::outs() << "ENTER " << rootAssignsToBoolean << "\n";
265+ std::optional<bool > &rootAssignsToBoolean) {
255266 if (!BinOp)
256267 return ;
257268
@@ -264,8 +275,6 @@ void BoolBitwiseOperationCheck::visitBinaryTreesNode(
264275 visitBinaryTreesNode (
265276 dyn_cast<BinaryOperator>(BinOp->getRHS ()->IgnoreParenImpCasts ()), BinOp,
266277 SM, Ctx, rootAssignsToBoolean);
267-
268- // llvm::outs() << "LEAVE\n";
269278}
270279
271280void BoolBitwiseOperationCheck::check (const MatchFinder::MatchResult &Result) {
0 commit comments