@@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
139139 return cast<BinaryOperator>(Left)->getOpcode () ==
140140 cast<BinaryOperator>(Right)->getOpcode ();
141141 case Stmt::UnaryExprOrTypeTraitExprClass:
142- const auto *LeftUnaryExpr =
143- cast<UnaryExprOrTypeTraitExpr>(Left);
144- const auto *RightUnaryExpr =
145- cast<UnaryExprOrTypeTraitExpr>(Right);
142+ const auto *LeftUnaryExpr = cast<UnaryExprOrTypeTraitExpr>(Left);
143+ const auto *RightUnaryExpr = cast<UnaryExprOrTypeTraitExpr>(Right);
146144 if (LeftUnaryExpr->isArgumentType () && RightUnaryExpr->isArgumentType ())
147145 return LeftUnaryExpr->getKind () == RightUnaryExpr->getKind () &&
148146 LeftUnaryExpr->getArgumentType () ==
@@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr(
699697
700698 Symbol = OverloadedOperatorExpr->getArg (IntegerConstantIsFirstArg ? 1 : 0 );
701699 OperandExpr = OverloadedOperatorExpr;
702- Opcode = BinaryOperator::getOverloadedOpcode (OverloadedOperatorExpr->getOperator ());
700+ Opcode = BinaryOperator::getOverloadedOpcode (
701+ OverloadedOperatorExpr->getOperator ());
703702
704703 if (!retrieveIntegerConstantExpr (Result, Id, Value, ConstExpr))
705704 return false ;
@@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr(
728727}
729728
730729// Checks for expressions like (X == 4) && (Y != 9)
731- static bool areSidesBinaryConstExpressions (const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
730+ static bool areSidesBinaryConstExpressions (const BinaryOperator *&BinOp,
731+ const ASTContext *AstCtx) {
732732 const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS ());
733733 const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS ());
734734
@@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A
747747 return false ;
748748}
749749
750+ static bool areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant (
751+ const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
752+ if (areSidesBinaryConstExpressions (BinOp, AstCtx))
753+ return true ;
754+
755+ const Expr *Lhs = BinOp->getLHS ();
756+ const Expr *Rhs = BinOp->getRHS ();
757+
758+ if (!Lhs || !Rhs)
759+ return false ;
760+
761+ auto IsDefineExpr = [AstCtx](const Expr *E) {
762+ const SourceRange Lsr = E->getSourceRange ();
763+ if (!Lsr.getBegin ().isMacroID () || E->isValueDependent () ||
764+ !E->isIntegerConstantExpr (*AstCtx))
765+ return false ;
766+ return true ;
767+ };
768+
769+ return IsDefineExpr (Lhs) || IsDefineExpr (Rhs);
770+ }
771+
750772// Retrieves integer constant subexpressions from binary operator expressions
751773// that have two equivalent sides.
752774// E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
@@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
785807}
786808
787809static bool isSameRawIdentifierToken (const Token &T1, const Token &T2,
788- const SourceManager &SM) {
810+ const SourceManager &SM) {
789811 if (T1.getKind () != T2.getKind ())
790812 return false ;
791813 if (T1.isNot (tok::raw_identifier))
@@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
808830 const ASTContext *AstCtx) {
809831 if (!LhsExpr || !RhsExpr)
810832 return false ;
811- SourceRange Lsr = LhsExpr->getSourceRange ();
812- SourceRange Rsr = RhsExpr->getSourceRange ();
833+ const SourceRange Lsr = LhsExpr->getSourceRange ();
834+ const SourceRange Rsr = RhsExpr->getSourceRange ();
813835 if (!Lsr.getBegin ().isMacroID () || !Rsr.getBegin ().isMacroID ())
814836 return false ;
815837
@@ -847,11 +869,104 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
847869 if (!LhsExpr || !RhsExpr)
848870 return false ;
849871
850- SourceLocation LhsLoc = LhsExpr->getExprLoc ();
851- SourceLocation RhsLoc = RhsExpr->getExprLoc ();
872+ const SourceLocation LhsLoc = LhsExpr->getExprLoc ();
873+ const SourceLocation RhsLoc = RhsExpr->getExprLoc ();
852874
853875 return LhsLoc.isMacroID () != RhsLoc.isMacroID ();
854876}
877+
878+ static bool areStringsSameIgnoreSpaces (const llvm::StringRef *Left,
879+ const llvm::StringRef *Right) {
880+ if (Left == Right)
881+ return true ;
882+ if (Left->compare (*Right) == 0 ) {
883+ return true ;
884+ }
885+ // Do running index comparison
886+ size_t LIdx = 0 ;
887+ size_t RIdx = 0 ;
888+ const char *LData = Left->data ();
889+ const char *RData = Right->data ();
890+ while (LIdx < Left->size () && RIdx < Right->size ()) {
891+
892+ // Skip spaces and tabs from both strings
893+ while (LIdx < Left->size () && (LData[LIdx] == ' ' || LData[LIdx] == ' \t ' )) {
894+ LIdx += 1 ;
895+ }
896+ while (RIdx < Right->size () &&
897+ (RData[RIdx] == ' ' || RData[RIdx] == ' \t ' )) {
898+ RIdx += 1 ;
899+ }
900+
901+ // If all not tabs and spaces are the same then return true
902+ if (LIdx >= Left->size () && RIdx >= Right->size ())
903+ return true ;
904+
905+ // If any characters differs then return false
906+ else if (LData[LIdx] != RData[RIdx])
907+ return false ;
908+
909+ // If current char is the same ==> continue search
910+ else {
911+ LIdx += 1 ;
912+ RIdx += 1 ;
913+ }
914+ }
915+ // Shortest string is processed: issue a verdict
916+ return LIdx >= Left->size () && RIdx >= Right->size ();
917+ }
918+
919+ static bool areExprsSameMacroOrLiteral (const BinaryOperator *BinOp,
920+ const ASTContext *Context) {
921+
922+ if (!BinOp)
923+ return false ;
924+
925+ const Expr *Lhs = BinOp->getLHS ();
926+ const Expr *Rhs = BinOp->getRHS ();
927+ const SourceManager &SM = Context->getSourceManager ();
928+
929+ const SourceRange Lsr = Lhs->getSourceRange ();
930+ const SourceRange Rsr = Rhs->getSourceRange ();
931+ if (Lsr.getBegin ().isMacroID ()) {
932+ // Left is macro so right macro too
933+ if (Rsr.getBegin ().isMacroID ()) {
934+ // Both sides are macros so they are same macro or literal
935+ const llvm::StringRef L = Lexer::getSourceText (
936+ CharSourceRange::getTokenRange (Lsr), SM, LangOptions (), 0 );
937+ const llvm::StringRef R = Lexer::getSourceText (
938+ CharSourceRange::getTokenRange (Rsr), SM, LangOptions (), 0 );
939+ return areStringsSameIgnoreSpaces (&L, &R);
940+ }
941+ // Left is macro but right is not so they are not same macro or literal
942+ return false ;
943+ } else {
944+ const auto *Lil = dyn_cast<IntegerLiteral>(Lhs);
945+ const auto *Ril = dyn_cast<IntegerLiteral>(Rhs);
946+ if (Lil && Ril) {
947+ return Lil->getValue () == Ril->getValue ();
948+ }
949+
950+ const auto *LStrl = dyn_cast<StringLiteral>(Lhs);
951+ const auto *RStrl = dyn_cast<StringLiteral>(Rhs);
952+ if (Lil && Ril) {
953+ const llvm::StringRef L = Lexer::getSourceText (
954+ CharSourceRange::getTokenRange (LStrl->getBeginLoc ()), SM,
955+ LangOptions (), 0 );
956+ const llvm::StringRef R = Lexer::getSourceText (
957+ CharSourceRange::getTokenRange (RStrl->getBeginLoc ()), SM,
958+ LangOptions (), 0 );
959+ return L.compare (R) == 0 ;
960+ }
961+
962+ const auto *Lbl = dyn_cast<CXXBoolLiteralExpr>(Lhs);
963+ const auto *Rbl = dyn_cast<CXXBoolLiteralExpr>(Rhs);
964+ if (Lbl && Rbl) {
965+ return Lbl->getValue () == Rbl->getValue ();
966+ }
967+ }
968+ return false ;
969+ }
855970} // namespace
856971
857972void RedundantExpressionCheck::registerMatchers (MatchFinder *Finder) {
@@ -1089,7 +1204,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
10891204 ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0 );
10901205}
10911206
1092-
10931207void RedundantExpressionCheck::checkBitwiseExpr (
10941208 const MatchFinder::MatchResult &Result) {
10951209 if (const auto *ComparisonOperator = Result.Nodes .getNodeAs <BinaryOperator>(
@@ -1134,8 +1248,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
11341248 ConstExpr))
11351249 return ;
11361250
1137- if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1138- return ;
1251+ if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1252+ return ;
11391253
11401254 SourceLocation Loc = IneffectiveOperator->getOperatorLoc ();
11411255
@@ -1276,19 +1390,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
12761390 return ;
12771391 }
12781392
1279- if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1393+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant (
1394+ BinOp, Result.Context )) {
12801395 const Expr *LhsConst = nullptr , *RhsConst = nullptr ;
12811396 BinaryOperatorKind MainOpcode{}, SideOpcode{};
1282-
1283- if (!retrieveConstExprFromBothSides (BinOp, MainOpcode, SideOpcode,
1284- LhsConst, RhsConst, Result.Context ))
1285- return ;
1286-
1287- if (areExprsFromDifferentMacros (LhsConst, RhsConst, Result.Context ) ||
1288- areExprsMacroAndNonMacro (LhsConst, RhsConst))
1289- return ;
1397+ if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1398+ if (!retrieveConstExprFromBothSides (BinOp, MainOpcode, SideOpcode,
1399+ LhsConst, RhsConst, Result.Context ))
1400+ return ;
1401+
1402+ if (areExprsFromDifferentMacros (LhsConst, RhsConst, Result.Context ) ||
1403+ areExprsMacroAndNonMacro (LhsConst, RhsConst))
1404+ return ;
1405+ } else {
1406+ if (!areExprsSameMacroOrLiteral (BinOp, Result.Context ))
1407+ return ;
1408+ }
12901409 }
1291-
12921410 diag (BinOp->getOperatorLoc (), " both sides of operator are equivalent" );
12931411 }
12941412
0 commit comments