@@ -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,83 @@ 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+
883+ // Do running comparison ignoring spaces
884+ llvm::StringRef L = Left.trim ();
885+ llvm::StringRef R = Right.trim ();
886+ while (!L.empty () && !R.empty ()) {
887+ L = L.ltrim ();
888+ R = R.ltrim ();
889+ if (L.empty () && R.empty ())
890+ return true ;
891+ // If symbol compared are different ==> strings are not the same
892+ if (L.front () != R.front ())
893+ return false ;
894+ L = L.drop_front ();
895+ R = R.drop_front ();
896+ }
897+ return L.empty () && R.empty ();
898+ }
899+
900+ static bool areExprsSameMacroOrLiteral (const BinaryOperator *BinOp,
901+ const ASTContext *Context) {
902+
903+ if (!BinOp)
904+ return false ;
905+
906+ const Expr *Lhs = BinOp->getLHS ();
907+ const Expr *Rhs = BinOp->getRHS ();
908+ const SourceManager &SM = Context->getSourceManager ();
909+
910+ const SourceRange Lsr = Lhs->getSourceRange ();
911+ const SourceRange Rsr = Rhs->getSourceRange ();
912+ if (Lsr.getBegin ().isMacroID ()) {
913+ // Left is macro so right macro too
914+ if (Rsr.getBegin ().isMacroID ()) {
915+ // Both sides are macros so they are same macro or literal
916+ const llvm::StringRef L = Lexer::getSourceText (
917+ CharSourceRange::getTokenRange (Lsr), SM, Context->getLangOpts (), 0 );
918+ const llvm::StringRef R = Lexer::getSourceText (
919+ CharSourceRange::getTokenRange (Rsr), SM, Context->getLangOpts (), 0 );
920+ return areStringsSameIgnoreSpaces (L, R);
921+ }
922+ // Left is macro but right is not so they are not same macro or literal
923+ return false ;
924+ }
925+ const auto *Lil = dyn_cast<IntegerLiteral>(Lhs);
926+ const auto *Ril = dyn_cast<IntegerLiteral>(Rhs);
927+ if (Lil && Ril)
928+ return Lil->getValue () == Ril->getValue ();
929+
930+ const auto *LStrl = dyn_cast<StringLiteral>(Lhs);
931+ const auto *RStrl = dyn_cast<StringLiteral>(Rhs);
932+ if (Lil && Ril) {
933+ const llvm::StringRef L = Lexer::getSourceText (
934+ CharSourceRange::getTokenRange (LStrl->getBeginLoc ()), SM,
935+ Context->getLangOpts (), 0 );
936+ const llvm::StringRef R = Lexer::getSourceText (
937+ CharSourceRange::getTokenRange (RStrl->getBeginLoc ()), SM,
938+ Context->getLangOpts (), 0 );
939+ return L.compare (R) == 0 ;
940+ }
941+
942+ const auto *Lbl = dyn_cast<CXXBoolLiteralExpr>(Lhs);
943+ const auto *Rbl = dyn_cast<CXXBoolLiteralExpr>(Rhs);
944+ if (Lbl && Rbl)
945+ return Lbl->getValue () == Rbl->getValue ();
946+
947+ return false ;
948+ }
855949} // namespace
856950
857951void RedundantExpressionCheck::registerMatchers (MatchFinder *Finder) {
@@ -1089,7 +1183,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
10891183 ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0 );
10901184}
10911185
1092-
10931186void RedundantExpressionCheck::checkBitwiseExpr (
10941187 const MatchFinder::MatchResult &Result) {
10951188 if (const auto *ComparisonOperator = Result.Nodes .getNodeAs <BinaryOperator>(
@@ -1134,8 +1227,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
11341227 ConstExpr))
11351228 return ;
11361229
1137- if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1138- return ;
1230+ if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1231+ return ;
11391232
11401233 SourceLocation Loc = IneffectiveOperator->getOperatorLoc ();
11411234
@@ -1276,19 +1369,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
12761369 return ;
12771370 }
12781371
1279- if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1372+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant (
1373+ BinOp, Result.Context )) {
12801374 const Expr *LhsConst = nullptr , *RhsConst = nullptr ;
12811375 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 ;
1376+ if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1377+ if (!retrieveConstExprFromBothSides (BinOp, MainOpcode, SideOpcode,
1378+ LhsConst, RhsConst, Result.Context ))
1379+ return ;
1380+
1381+ if (areExprsFromDifferentMacros (LhsConst, RhsConst, Result.Context ) ||
1382+ areExprsMacroAndNonMacro (LhsConst, RhsConst))
1383+ return ;
1384+ } else {
1385+ if (!areExprsSameMacroOrLiteral (BinOp, Result.Context ))
1386+ return ;
1387+ }
12901388 }
1291-
12921389 diag (BinOp->getOperatorLoc (), " both sides of operator are equivalent" );
12931390 }
12941391
0 commit comments