@@ -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,102 @@ 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+ while (LIdx < Left->size () && (LData[LIdx] == ' ' || LData[LIdx] == ' \t ' )) {
892+ LIdx++;
893+ }
894+ while (RIdx < Right->size () &&
895+ (RData[RIdx] == ' ' || RData[RIdx] == ' \t ' )) {
896+ RIdx++;
897+ }
898+
899+ // If all not tabs and spaces are the same then return true
900+ if (LIdx == Left->size () && RIdx == Right->size ())
901+ return true ;
902+
903+ // If any characters differs then return false
904+ else if (LData[LIdx] != RData[RIdx])
905+ return false ;
906+
907+ // If current char is the same ==> continue search
908+ else {
909+ LIdx += 1 ;
910+ RIdx += 1 ;
911+ }
912+ }
913+ // If we reach here then we have real length difference
914+ return LIdx == Left->size () && RIdx == Right->size ();
915+ }
916+
917+ static bool areExprsSameMacroOrLiteral (const BinaryOperator *BinOp,
918+ const ASTContext *Context) {
919+
920+ if (!BinOp)
921+ return false ;
922+
923+ const Expr *Lhs = BinOp->getLHS ();
924+ const Expr *Rhs = BinOp->getRHS ();
925+ const SourceManager &SM = Context->getSourceManager ();
926+
927+ const SourceRange Lsr = Lhs->getSourceRange ();
928+ const SourceRange Rsr = Rhs->getSourceRange ();
929+ if (Lsr.getBegin ().isMacroID ()) {
930+ // Left is macro so right macro too
931+ if (Rsr.getBegin ().isMacroID ()) {
932+ // Both sides are macros so they are same macro or literal
933+ llvm::StringRef L = Lexer::getSourceText (
934+ CharSourceRange::getTokenRange (Lsr), SM, LangOptions (), 0 );
935+ llvm::StringRef R = Lexer::getSourceText (
936+ CharSourceRange::getTokenRange (Rsr), SM, LangOptions (), 0 );
937+ return areStringsSameIgnoreSpaces (&L, &R);
938+ }
939+ // Left is macro but right is not so they are not same macro or literal
940+ return false ;
941+ } else {
942+ const auto *Lil = dyn_cast<IntegerLiteral>(Lhs);
943+ const auto *Ril = dyn_cast<IntegerLiteral>(Rhs);
944+ if (Lil && Ril) {
945+ return Lil->getValue () == Ril->getValue ();
946+ }
947+
948+ const auto *LStrl = dyn_cast<StringLiteral>(Lhs);
949+ const auto *RStrl = dyn_cast<StringLiteral>(Rhs);
950+ if (Lil && Ril) {
951+ llvm::StringRef L = Lexer::getSourceText (
952+ CharSourceRange::getTokenRange (LStrl->getBeginLoc ()), SM,
953+ LangOptions (), 0 );
954+ llvm::StringRef R = Lexer::getSourceText (
955+ CharSourceRange::getTokenRange (RStrl->getBeginLoc ()), SM,
956+ LangOptions (), 0 );
957+ return L.compare (R) == 0 ;
958+ }
959+
960+ const auto *Lbl = dyn_cast<CXXBoolLiteralExpr>(Lhs);
961+ const auto *Rbl = dyn_cast<CXXBoolLiteralExpr>(Rhs);
962+ if (Lbl && Rbl) {
963+ return Lbl->getValue () == Rbl->getValue ();
964+ }
965+ }
966+ return false ;
967+ }
855968} // namespace
856969
857970void RedundantExpressionCheck::registerMatchers (MatchFinder *Finder) {
@@ -1089,7 +1202,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
10891202 ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0 );
10901203}
10911204
1092-
10931205void RedundantExpressionCheck::checkBitwiseExpr (
10941206 const MatchFinder::MatchResult &Result) {
10951207 if (const auto *ComparisonOperator = Result.Nodes .getNodeAs <BinaryOperator>(
@@ -1134,8 +1246,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
11341246 ConstExpr))
11351247 return ;
11361248
1137- if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1138- return ;
1249+ if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1250+ return ;
11391251
11401252 SourceLocation Loc = IneffectiveOperator->getOperatorLoc ();
11411253
@@ -1276,19 +1388,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
12761388 return ;
12771389 }
12781390
1279- if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1391+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant (
1392+ BinOp, Result.Context )) {
12801393 const Expr *LhsConst = nullptr , *RhsConst = nullptr ;
12811394 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 ;
1395+ if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1396+ if (!retrieveConstExprFromBothSides (BinOp, MainOpcode, SideOpcode,
1397+ LhsConst, RhsConst, Result.Context ))
1398+ return ;
1399+
1400+ if (areExprsFromDifferentMacros (LhsConst, RhsConst, Result.Context ) ||
1401+ areExprsMacroAndNonMacro (LhsConst, RhsConst))
1402+ return ;
1403+ } else {
1404+ if (!areExprsSameMacroOrLiteral (BinOp, Result.Context ))
1405+ return ;
1406+ }
12901407 }
1291-
12921408 diag (BinOp->getOperatorLoc (), " both sides of operator are equivalent" );
12931409 }
12941410
0 commit comments