@@ -139,10 +139,8 @@ static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
139
139
return cast<BinaryOperator>(Left)->getOpcode () ==
140
140
cast<BinaryOperator>(Right)->getOpcode ();
141
141
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);
146
144
if (LeftUnaryExpr->isArgumentType () && RightUnaryExpr->isArgumentType ())
147
145
return LeftUnaryExpr->getKind () == RightUnaryExpr->getKind () &&
148
146
LeftUnaryExpr->getArgumentType () ==
@@ -699,7 +697,8 @@ static bool retrieveRelationalIntegerConstantExpr(
699
697
700
698
Symbol = OverloadedOperatorExpr->getArg (IntegerConstantIsFirstArg ? 1 : 0 );
701
699
OperandExpr = OverloadedOperatorExpr;
702
- Opcode = BinaryOperator::getOverloadedOpcode (OverloadedOperatorExpr->getOperator ());
700
+ Opcode = BinaryOperator::getOverloadedOpcode (
701
+ OverloadedOperatorExpr->getOperator ());
703
702
704
703
if (!retrieveIntegerConstantExpr (Result, Id, Value, ConstExpr))
705
704
return false ;
@@ -728,7 +727,8 @@ static bool retrieveRelationalIntegerConstantExpr(
728
727
}
729
728
730
729
// 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) {
732
732
const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS ());
733
733
const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS ());
734
734
@@ -747,6 +747,28 @@ static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const A
747
747
return false ;
748
748
}
749
749
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
+
750
772
// Retrieves integer constant subexpressions from binary operator expressions
751
773
// that have two equivalent sides.
752
774
// E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
@@ -785,7 +807,7 @@ static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
785
807
}
786
808
787
809
static bool isSameRawIdentifierToken (const Token &T1, const Token &T2,
788
- const SourceManager &SM) {
810
+ const SourceManager &SM) {
789
811
if (T1.getKind () != T2.getKind ())
790
812
return false ;
791
813
if (T1.isNot (tok::raw_identifier))
@@ -808,8 +830,8 @@ static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
808
830
const ASTContext *AstCtx) {
809
831
if (!LhsExpr || !RhsExpr)
810
832
return false ;
811
- SourceRange Lsr = LhsExpr->getSourceRange ();
812
- SourceRange Rsr = RhsExpr->getSourceRange ();
833
+ const SourceRange Lsr = LhsExpr->getSourceRange ();
834
+ const SourceRange Rsr = RhsExpr->getSourceRange ();
813
835
if (!Lsr.getBegin ().isMacroID () || !Rsr.getBegin ().isMacroID ())
814
836
return false ;
815
837
@@ -847,11 +869,83 @@ static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
847
869
if (!LhsExpr || !RhsExpr)
848
870
return false ;
849
871
850
- SourceLocation LhsLoc = LhsExpr->getExprLoc ();
851
- SourceLocation RhsLoc = RhsExpr->getExprLoc ();
872
+ const SourceLocation LhsLoc = LhsExpr->getExprLoc ();
873
+ const SourceLocation RhsLoc = RhsExpr->getExprLoc ();
852
874
853
875
return LhsLoc.isMacroID () != RhsLoc.isMacroID ();
854
876
}
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
+ }
855
949
} // namespace
856
950
857
951
void RedundantExpressionCheck::registerMatchers (MatchFinder *Finder) {
@@ -1089,7 +1183,6 @@ static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
1089
1183
((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0 );
1090
1184
}
1091
1185
1092
-
1093
1186
void RedundantExpressionCheck::checkBitwiseExpr (
1094
1187
const MatchFinder::MatchResult &Result) {
1095
1188
if (const auto *ComparisonOperator = Result.Nodes .getNodeAs <BinaryOperator>(
@@ -1134,8 +1227,8 @@ void RedundantExpressionCheck::checkBitwiseExpr(
1134
1227
ConstExpr))
1135
1228
return ;
1136
1229
1137
- if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1138
- return ;
1230
+ if ((Value != 0 && ~Value != 0 ) || Sym->getExprLoc ().isMacroID ())
1231
+ return ;
1139
1232
1140
1233
SourceLocation Loc = IneffectiveOperator->getOperatorLoc ();
1141
1234
@@ -1276,19 +1369,23 @@ void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
1276
1369
return ;
1277
1370
}
1278
1371
1279
- if (areSidesBinaryConstExpressions (BinOp, Result.Context )) {
1372
+ if (areSidesBinaryConstExpressionsOrDefinesOrIntegerConstant (
1373
+ BinOp, Result.Context )) {
1280
1374
const Expr *LhsConst = nullptr , *RhsConst = nullptr ;
1281
1375
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
+ }
1290
1388
}
1291
-
1292
1389
diag (BinOp->getOperatorLoc (), " both sides of operator are equivalent" );
1293
1390
}
1294
1391
0 commit comments