11 #include "../utils/Matchers.h" 12 #include "../utils/OptionsUtils.h" 13 #include "clang/AST/ASTContext.h" 14 #include "clang/ASTMatchers/ASTMatchFinder.h" 15 #include "clang/Basic/LLVM.h" 16 #include "clang/Basic/SourceLocation.h" 17 #include "clang/Basic/SourceManager.h" 18 #include "clang/Lex/Lexer.h" 19 #include "llvm/ADT/APInt.h" 20 #include "llvm/ADT/APSInt.h" 21 #include "llvm/ADT/FoldingSet.h" 22 #include "llvm/Support/Casting.h" 47 return Value < Result;
51 const NestedNameSpecifier *Right) {
52 llvm::FoldingSetNodeID LeftID, RightID;
53 Left->Profile(LeftID);
54 Right->Profile(RightID);
55 return LeftID == RightID;
60 return !Left && !Right;
62 Left = Left->IgnoreParens();
63 Right = Right->IgnoreParens();
66 if (Left->getStmtClass() != Right->getStmtClass())
70 Expr::const_child_iterator LeftIter = Left->child_begin();
71 Expr::const_child_iterator RightIter = Right->child_begin();
72 while (LeftIter != Left->child_end() && RightIter != Right->child_end()) {
74 dyn_cast<Expr>(*RightIter)))
79 if (LeftIter != Left->child_end() || RightIter != Right->child_end())
83 switch (Left->getStmtClass()) {
87 case Stmt::CharacterLiteralClass:
88 return cast<CharacterLiteral>(Left)->getValue() ==
89 cast<CharacterLiteral>(Right)->getValue();
90 case Stmt::IntegerLiteralClass: {
91 llvm::APInt LeftLit = cast<IntegerLiteral>(Left)->getValue();
92 llvm::APInt RightLit = cast<IntegerLiteral>(Right)->getValue();
93 return LeftLit.getBitWidth() == RightLit.getBitWidth() &&
96 case Stmt::FloatingLiteralClass:
97 return cast<FloatingLiteral>(Left)->getValue().bitwiseIsEqual(
98 cast<FloatingLiteral>(Right)->getValue());
99 case Stmt::StringLiteralClass:
100 return cast<StringLiteral>(Left)->getBytes() ==
101 cast<StringLiteral>(Right)->getBytes();
102 case Stmt::CXXOperatorCallExprClass:
103 return cast<CXXOperatorCallExpr>(Left)->getOperator() ==
104 cast<CXXOperatorCallExpr>(Right)->getOperator();
105 case Stmt::DependentScopeDeclRefExprClass:
106 if (cast<DependentScopeDeclRefExpr>(Left)->getDeclName() !=
107 cast<DependentScopeDeclRefExpr>(Right)->getDeclName())
110 cast<DependentScopeDeclRefExpr>(Left)->getQualifier(),
111 cast<DependentScopeDeclRefExpr>(Right)->getQualifier());
112 case Stmt::DeclRefExprClass:
113 return cast<DeclRefExpr>(Left)->getDecl() ==
114 cast<DeclRefExpr>(Right)->getDecl();
115 case Stmt::MemberExprClass:
116 return cast<MemberExpr>(Left)->getMemberDecl() ==
117 cast<MemberExpr>(Right)->getMemberDecl();
118 case Stmt::CXXFunctionalCastExprClass:
119 case Stmt::CStyleCastExprClass:
120 return cast<ExplicitCastExpr>(Left)->getTypeAsWritten() ==
121 cast<ExplicitCastExpr>(Right)->getTypeAsWritten();
122 case Stmt::CallExprClass:
123 case Stmt::ImplicitCastExprClass:
124 case Stmt::ArraySubscriptExprClass:
126 case Stmt::UnaryOperatorClass:
127 if (cast<UnaryOperator>(Left)->isIncrementDecrementOp())
129 return cast<UnaryOperator>(Left)->getOpcode() ==
130 cast<UnaryOperator>(Right)->getOpcode();
131 case Stmt::BinaryOperatorClass:
132 return cast<BinaryOperator>(Left)->getOpcode() ==
133 cast<BinaryOperator>(Right)->getOpcode();
140 const APSInt &ValueLHS,
141 BinaryOperatorKind OpcodeRHS,
142 const APSInt &ValueRHS) {
143 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
144 "Values must be ordered");
146 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0)
147 return OpcodeLHS == OpcodeRHS;
150 APSInt ValueLHS_plus1;
151 return ((OpcodeLHS == BO_LE && OpcodeRHS == BO_LT) ||
152 (OpcodeLHS == BO_GT && OpcodeRHS == BO_GE)) &&
154 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0;
160 const APSInt &ValueLHS,
161 BinaryOperatorKind OpcodeRHS,
162 const APSInt &ValueRHS) {
163 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
164 "Values must be ordered");
167 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
170 return OpcodeRHS == BO_NE || OpcodeRHS == BO_GT || OpcodeRHS == BO_LT;
172 return OpcodeRHS == BO_EQ;
174 return OpcodeRHS == BO_GT;
176 return OpcodeRHS == BO_LT;
178 return OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
180 return OpcodeRHS == BO_EQ || OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
187 if ((OpcodeLHS == BO_EQ || OpcodeLHS == BO_LT || OpcodeLHS == BO_LE) &&
188 (OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE))
192 APSInt ValueLHS_plus1;
193 if (OpcodeLHS == BO_GT && OpcodeRHS == BO_LT &&
195 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
204 const APSInt &ValueLHS,
205 BinaryOperatorKind OpcodeRHS,
206 const APSInt &ValueRHS) {
207 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
208 "Values must be ordered");
211 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
214 return OpcodeRHS == BO_NE;
216 return OpcodeRHS == BO_EQ;
218 return OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
220 return OpcodeRHS == BO_GE;
222 return OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
224 return OpcodeRHS == BO_LE;
231 APSInt ValueLHS_plus1;
232 if (OpcodeLHS == BO_LE && OpcodeRHS == BO_GE &&
234 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
238 if ((OpcodeLHS == BO_GT || OpcodeLHS == BO_GE) &&
239 (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE))
244 if (OpcodeLHS == BO_NE && OpcodeRHS == BO_NE)
251 const APSInt &ValueLHS,
252 BinaryOperatorKind OpcodeRHS,
253 const APSInt &ValueRHS) {
254 int Comparison = APSInt::compareValues(ValueLHS, ValueRHS);
257 return OpcodeRHS == BO_EQ && Comparison == 0;
259 return (OpcodeRHS == BO_NE && Comparison == 0) ||
260 (OpcodeRHS == BO_EQ && Comparison != 0) ||
261 (OpcodeRHS == BO_LT && Comparison >= 0) ||
262 (OpcodeRHS == BO_LE && Comparison > 0) ||
263 (OpcodeRHS == BO_GT && Comparison <= 0) ||
264 (OpcodeRHS == BO_GE && Comparison < 0);
267 return ((OpcodeRHS == BO_LT && Comparison >= 0) ||
268 (OpcodeRHS == BO_LE && Comparison > 0) ||
269 (OpcodeRHS == BO_EQ && Comparison > 0));
271 return ((OpcodeRHS == BO_GT && Comparison <= 0) ||
272 (OpcodeRHS == BO_GE && Comparison < 0) ||
273 (OpcodeRHS == BO_EQ && Comparison < 0));
275 return (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE || OpcodeRHS == BO_EQ) &&
278 return (OpcodeRHS == BO_GT || OpcodeRHS == BO_GE || OpcodeRHS == BO_EQ) &&
287 if (Opcode == BO_Sub) {
294 if (Node.isInstantiationDependent())
296 return Node.isIntegerConstantExpr(Finder->getASTContext());
308 return Node.getNumArgs() == 2 &&
313 return Node.getOperatorLoc().isMacroID();
317 return Node.getQuestionLoc().isMacroID() || Node.getColonLoc().isMacroID();
320 AST_MATCHER(Expr, isMacro) {
return Node.getExprLoc().isMacroID(); }
323 const SourceManager &SM = Finder->getASTContext().getSourceManager();
324 const LangOptions &LO = Finder->getASTContext().getLangOpts();
325 SourceLocation
Loc = Node.getExprLoc();
326 while (Loc.isMacroID()) {
327 StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LO);
328 if (Names.count(MacroName))
330 Loc = SM.getImmediateMacroCallerLoc(Loc);
336 static ast_matchers::internal::Matcher<Expr>
338 std::string CstId = (Id +
"-const").str();
339 return expr(isIntegerConstantExpr()).bind(CstId);
346 StringRef Id, APSInt &Value,
347 const Expr *&ConstExpr) {
348 std::string CstId = (Id +
"-const").str();
349 ConstExpr = Result.Nodes.getNodeAs<Expr>(CstId);
350 return ConstExpr && ConstExpr->isIntegerConstantExpr(Value, *Result.Context);
355 StringRef Id, APSInt &Value) {
356 const Expr *ConstExpr =
nullptr;
363 std::string SymId = (Id +
"-sym").str();
364 return ignoringParenImpCasts(
365 expr(unless(isIntegerConstantExpr())).bind(SymId));
371 StringRef Id,
const Expr *&SymExpr) {
372 std::string SymId = (Id +
"-sym").str();
373 if (
const auto *Node = Result.Nodes.getNodeAs<Expr>(SymId)) {
382 static ast_matchers::internal::Matcher<Expr>
384 const auto BinOpCstExpr =
386 anyOf(binaryOperator(anyOf(hasOperatorName(
"+"), hasOperatorName(
"|"),
387 hasOperatorName(
"&")),
390 binaryOperator(hasOperatorName(
"-"),
394 return ignoringParenImpCasts(BinOpCstExpr);
401 StringRef Id, BinaryOperatorKind &Opcode,
402 const Expr *&Symbol, APSInt &Value) {
403 if (
const auto *BinExpr = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
404 Opcode = BinExpr->getOpcode();
412 static ast_matchers::internal::Matcher<Expr>
414 std::string CastId = (Id +
"-cast").str();
415 std::string SwapId = (Id +
"-swap").str();
416 std::string NegateId = (Id +
"-negate").str();
417 std::string OverloadId = (Id +
"-overload").str();
419 const auto RelationalExpr = ignoringParenImpCasts(binaryOperator(
420 isComparisonOperator(), expr().bind(Id),
428 const auto CastExpr =
429 implicitCastExpr(hasCastKind(CK_IntegralToBoolean),
433 const auto NegateRelationalExpr =
434 unaryOperator(hasOperatorName(
"!"),
435 hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))
439 const auto NegateNegateRelationalExpr =
440 unaryOperator(hasOperatorName(
"!"),
441 hasUnaryOperand(unaryOperator(
442 hasOperatorName(
"!"),
443 hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))));
445 const auto OverloadedOperatorExpr =
447 anyOf(hasOverloadedOperatorName(
"=="),
448 hasOverloadedOperatorName(
"!="), hasOverloadedOperatorName(
"<"),
449 hasOverloadedOperatorName(
"<="), hasOverloadedOperatorName(
">"),
450 hasOverloadedOperatorName(
">=")),
452 unless(isMacro()), unless(isInTemplateInstantiation()))
455 return anyOf(RelationalExpr, CastExpr, NegateRelationalExpr,
456 NegateNegateRelationalExpr, OverloadedOperatorExpr);
462 return ParamType->isReferenceType() &&
463 !ParamType.getNonReferenceType().isConstQualified();
474 bool checkSecondParam) {
475 unsigned ParamCount = OperatorDecl->getNumParams();
480 if (ParamCount == 1 &&
481 !OperatorDecl->getType()->getAs<FunctionType>()->isConst())
487 return checkSecondParam && ParamCount == 2 &&
494 const MatchFinder::MatchResult &Result, StringRef Id,
495 const Expr *&OperandExpr, BinaryOperatorKind &Opcode,
const Expr *&Symbol,
496 APSInt &Value,
const Expr *&ConstExpr) {
497 std::string CastId = (Id +
"-cast").str();
498 std::string SwapId = (Id +
"-swap").str();
499 std::string NegateId = (Id +
"-negate").str();
500 std::string OverloadId = (Id +
"-overload").str();
502 if (
const auto *Bin = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
504 Opcode = Bin->getOpcode();
509 }
else if (
const auto *Cast = Result.Nodes.getNodeAs<CastExpr>(CastId)) {
513 Value = APSInt(32,
false);
514 }
else if (
const auto *OverloadedOperatorExpr =
515 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(OverloadId)) {
516 const auto *OverloadedFunctionDecl = dyn_cast_or_null<FunctionDecl>(OverloadedOperatorExpr->getCalleeDecl());
517 if (!OverloadedFunctionDecl)
526 if (!OverloadedOperatorExpr->getArg(1)->isIntegerConstantExpr(
527 Value, *Result.Context))
530 Symbol = OverloadedOperatorExpr->getArg(0);
531 OperandExpr = OverloadedOperatorExpr;
532 Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());
534 return BinaryOperator::isComparisonOp(Opcode);
542 if (Result.Nodes.getNodeAs<Expr>(SwapId))
543 Opcode = BinaryOperator::reverseComparisonOp(Opcode);
544 if (Result.Nodes.getNodeAs<Expr>(NegateId))
545 Opcode = BinaryOperator::negateComparisonOp(Opcode);
551 const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS());
552 const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS());
554 if (!LhsBinOp || !RhsBinOp)
557 if ((LhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
558 LhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)) &&
559 (RhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
560 RhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)))
569 BinaryOperatorKind &MainOpcode,
570 BinaryOperatorKind &SideOpcode,
571 const Expr *&LhsConst,
572 const Expr *&RhsConst,
573 const ASTContext *AstCtx) {
575 "Both sides of binary operator must be constant expressions!");
577 MainOpcode = BinOp->getOpcode();
579 const auto *BinOpLhs = cast<BinaryOperator>(BinOp->getLHS());
580 const auto *BinOpRhs = cast<BinaryOperator>(BinOp->getRHS());
582 LhsConst = BinOpLhs->getLHS()->isIntegerConstantExpr(*AstCtx)
584 : BinOpLhs->getRHS();
585 RhsConst = BinOpRhs->getLHS()->isIntegerConstantExpr(*AstCtx)
587 : BinOpRhs->getRHS();
589 if (!LhsConst || !RhsConst)
592 assert(BinOpLhs->getOpcode() == BinOpRhs->getOpcode() &&
593 "Sides of the binary operator must be equivalent expressions!");
595 SideOpcode = BinOpLhs->getOpcode();
602 const ASTContext *AstCtx) {
603 if (!LhsExpr || !RhsExpr)
606 SourceLocation LhsLoc = LhsExpr->getExprLoc();
607 SourceLocation RhsLoc = RhsExpr->getExprLoc();
609 if (!LhsLoc.isMacroID() || !RhsLoc.isMacroID())
612 const SourceManager &SM = AstCtx->getSourceManager();
613 const LangOptions &LO = AstCtx->getLangOpts();
615 return !(Lexer::getImmediateMacroName(LhsLoc, SM, LO) ==
616 Lexer::getImmediateMacroName(RhsLoc, SM, LO));
620 const Expr *&RhsExpr) {
621 if (!LhsExpr || !RhsExpr)
624 SourceLocation LhsLoc = LhsExpr->getExprLoc();
625 SourceLocation RhsLoc = RhsExpr->getExprLoc();
627 return LhsLoc.isMacroID() != RhsLoc.isMacroID();
630 void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
631 const auto AnyLiteralExpr = ignoringParenImpCasts(
632 anyOf(cxxBoolLiteral(), characterLiteral(), integerLiteral()));
634 const auto BannedIntegerLiteral =
635 integerLiteral(expandedByMacro(KnownBannedMacroNames));
639 binaryOperator(anyOf(hasOperatorName(
"-"), hasOperatorName(
"/"),
640 hasOperatorName(
"%"), hasOperatorName(
"|"),
641 hasOperatorName(
"&"), hasOperatorName(
"^"),
642 matchers::isComparisonOperator(),
643 hasOperatorName(
"&&"), hasOperatorName(
"||"),
644 hasOperatorName(
"=")),
645 operandsAreEquivalent(),
647 unless(isInTemplateInstantiation()),
648 unless(binaryOperatorIsInMacro()),
649 unless(hasType(realFloatingPointType())),
650 unless(hasEitherOperand(hasType(realFloatingPointType()))),
651 unless(hasLHS(AnyLiteralExpr)),
652 unless(hasDescendant(BannedIntegerLiteral)))
657 Finder->addMatcher(conditionalOperator(expressionsAreEquivalent(),
659 unless(conditionalOperatorIsInMacro()),
660 unless(isInTemplateInstantiation()))
668 hasOverloadedOperatorName(
"-"), hasOverloadedOperatorName(
"/"),
669 hasOverloadedOperatorName(
"%"), hasOverloadedOperatorName(
"|"),
670 hasOverloadedOperatorName(
"&"), hasOverloadedOperatorName(
"^"),
671 hasOverloadedOperatorName(
"=="), hasOverloadedOperatorName(
"!="),
672 hasOverloadedOperatorName(
"<"), hasOverloadedOperatorName(
"<="),
673 hasOverloadedOperatorName(
">"), hasOverloadedOperatorName(
">="),
674 hasOverloadedOperatorName(
"&&"), hasOverloadedOperatorName(
"||"),
675 hasOverloadedOperatorName(
"=")),
676 parametersAreEquivalent(),
678 unless(isMacro()), unless(isInTemplateInstantiation()))
685 hasImplicitDestinationType(isInteger()),
687 hasOperatorName(
"!"),
688 hasUnaryOperand(ignoringParenImpCasts(binaryOperator(
689 anyOf(hasOperatorName(
"|"), hasOperatorName(
"&")),
690 hasLHS(anyOf(binaryOperator(anyOf(hasOperatorName(
"|"),
691 hasOperatorName(
"&"))),
693 hasRHS(integerLiteral())))))
694 .bind(
"logical-bitwise-confusion"))),
699 binaryOperator(hasOperatorName(
"&"),
700 hasEitherOperand(ignoringParenImpCasts(binaryOperator(
701 hasOperatorName(
"<<"),
702 hasRHS(ignoringParenImpCasts(
703 integerLiteral().bind(
"shift-const")))))),
704 hasEitherOperand(ignoringParenImpCasts(
705 integerLiteral().bind(
"and-const"))))
706 .bind(
"left-right-shift-confusion"),
721 Finder->addMatcher(binaryOperator(isComparisonOperator(),
722 hasEitherOperand(BinOpCstLeft),
723 hasEitherOperand(CstRight))
724 .bind(
"binop-const-compare-to-const"),
729 binaryOperator(isComparisonOperator(),
730 anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)),
731 allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft))))
732 .bind(
"binop-const-compare-to-sym"),
736 Finder->addMatcher(binaryOperator(isComparisonOperator(),
737 hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight),
739 unless(operandsAreEquivalent()))
740 .bind(
"binop-const-compare-to-binop-const"),
751 binaryOperator(anyOf(hasOperatorName(
"||"), hasOperatorName(
"&&")),
752 hasLHS(ComparisonLeft), hasRHS(ComparisonRight),
754 unless(operandsAreEquivalent()))
755 .bind(
"comparisons-of-symbol-and-const"),
759 void RedundantExpressionCheck::checkArithmeticExpr(
760 const MatchFinder::MatchResult &Result) {
761 APSInt LhsValue, RhsValue;
762 const Expr *LhsSymbol =
nullptr, *RhsSymbol =
nullptr;
763 BinaryOperatorKind LhsOpcode, RhsOpcode;
765 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
766 "binop-const-compare-to-sym")) {
767 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
775 if (LhsOpcode == BO_Add || LhsOpcode == BO_Sub) {
776 if ((LhsValue != 0 && Opcode == BO_EQ) ||
777 (LhsValue == 0 && Opcode == BO_NE))
778 diag(ComparisonOperator->getOperatorLoc(),
779 "logical expression is always false");
780 else if ((LhsValue == 0 && Opcode == BO_EQ) ||
781 (LhsValue != 0 && Opcode == BO_NE))
782 diag(ComparisonOperator->getOperatorLoc(),
783 "logical expression is always true");
785 }
else if (
const auto *ComparisonOperator =
786 Result.Nodes.getNodeAs<BinaryOperator>(
787 "binop-const-compare-to-binop-const")) {
788 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
801 if (LhsOpcode == BO_Add && RhsOpcode == BO_Add) {
802 if ((Opcode == BO_EQ && APSInt::compareValues(LhsValue, RhsValue) == 0) ||
803 (Opcode == BO_NE && APSInt::compareValues(LhsValue, RhsValue) != 0)) {
804 diag(ComparisonOperator->getOperatorLoc(),
805 "logical expression is always true");
806 }
else if ((Opcode == BO_EQ &&
807 APSInt::compareValues(LhsValue, RhsValue) != 0) ||
809 APSInt::compareValues(LhsValue, RhsValue) == 0)) {
810 diag(ComparisonOperator->getOperatorLoc(),
811 "logical expression is always false");
818 return (Opcode == BO_And || Opcode == BO_AndAssign) && Value == 0;
823 return (Opcode == BO_Or || Opcode == BO_OrAssign) && ~Value == 0;
827 return ((Opcode == BO_Or || Opcode == BO_OrAssign) && Value == 0) ||
828 ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
832 void RedundantExpressionCheck::checkBitwiseExpr(
833 const MatchFinder::MatchResult &Result) {
834 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
835 "binop-const-compare-to-const")) {
836 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
838 APSInt LhsValue, RhsValue;
839 const Expr *LhsSymbol =
nullptr;
840 BinaryOperatorKind LhsOpcode;
846 uint64_t LhsConstant = LhsValue.getZExtValue();
847 uint64_t RhsConstant = RhsValue.getZExtValue();
848 SourceLocation
Loc = ComparisonOperator->getOperatorLoc();
851 if (LhsOpcode == BO_And && (LhsConstant & RhsConstant) != RhsConstant) {
853 diag(Loc,
"logical expression is always false");
854 else if (Opcode == BO_NE)
855 diag(Loc,
"logical expression is always true");
859 if (LhsOpcode == BO_Or && (LhsConstant | RhsConstant) != RhsConstant) {
861 diag(Loc,
"logical expression is always false");
862 else if (Opcode == BO_NE)
863 diag(Loc,
"logical expression is always true");
865 }
else if (
const auto *IneffectiveOperator =
866 Result.Nodes.getNodeAs<BinaryOperator>(
867 "ineffective-bitwise")) {
869 const Expr *Sym =
nullptr, *ConstExpr =
nullptr;
876 if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
879 SourceLocation
Loc = IneffectiveOperator->getOperatorLoc();
881 BinaryOperatorKind Opcode = IneffectiveOperator->getOpcode();
883 diag(Loc,
"expression always evaluates to 0");
885 SourceRange ConstExprRange(ConstExpr->getLocStart(),
886 ConstExpr->getLocEnd());
887 StringRef ConstExprText = Lexer::getSourceText(
888 CharSourceRange::getTokenRange(ConstExprRange), *Result.SourceManager,
889 Result.Context->getLangOpts());
891 diag(Loc,
"expression always evaluates to '%0'") << ConstExprText;
894 SourceRange SymExprRange(Sym->getLocStart(), Sym->getLocEnd());
896 StringRef ExprText = Lexer::getSourceText(
897 CharSourceRange::getTokenRange(SymExprRange), *Result.SourceManager,
898 Result.Context->getLangOpts());
900 diag(Loc,
"expression always evaluates to '%0'") << ExprText;
905 void RedundantExpressionCheck::checkRelationalExpr(
906 const MatchFinder::MatchResult &Result) {
907 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
908 "comparisons-of-symbol-and-const")) {
911 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
913 const Expr *LhsExpr =
nullptr, *RhsExpr =
nullptr;
914 const Expr *LhsSymbol =
nullptr, *RhsSymbol =
nullptr;
915 const Expr *LhsConst =
nullptr, *RhsConst =
nullptr;
916 BinaryOperatorKind LhsOpcode, RhsOpcode;
917 APSInt LhsValue, RhsValue;
920 Result,
"lhs", LhsExpr, LhsOpcode, LhsSymbol, LhsValue, LhsConst) ||
922 Result,
"rhs", RhsExpr, RhsOpcode, RhsSymbol, RhsValue, RhsConst) ||
927 if (APSInt::compareValues(LhsValue, RhsValue) > 0) {
928 std::swap(LhsExpr, RhsExpr);
929 std::swap(LhsValue, RhsValue);
930 std::swap(LhsSymbol, RhsSymbol);
931 std::swap(LhsOpcode, RhsOpcode);
939 if ((Opcode == BO_LAnd || Opcode == BO_LOr) &&
941 diag(ComparisonOperator->getOperatorLoc(),
942 "equivalent expression on both sides of logical operator");
946 if (Opcode == BO_LAnd) {
948 diag(ComparisonOperator->getOperatorLoc(),
949 "logical expression is always false");
951 diag(LhsExpr->getExprLoc(),
"expression is redundant");
953 diag(RhsExpr->getExprLoc(),
"expression is redundant");
957 if (Opcode == BO_LOr) {
959 diag(ComparisonOperator->getOperatorLoc(),
960 "logical expression is always true");
962 diag(RhsExpr->getExprLoc(),
"expression is redundant");
964 diag(LhsExpr->getExprLoc(),
"expression is redundant");
970 void RedundantExpressionCheck::check(
const MatchFinder::MatchResult &Result) {
971 if (
const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"binary")) {
975 const Expr *LhsConst =
nullptr, *RhsConst =
nullptr;
976 BinaryOperatorKind MainOpcode, SideOpcode;
979 LhsConst, RhsConst, Result.Context))
987 diag(BinOp->getOperatorLoc(),
"both sides of operator are equivalent");
990 if (
const auto *CondOp =
991 Result.Nodes.getNodeAs<ConditionalOperator>(
"cond")) {
992 const Expr *TrueExpr = CondOp->getTrueExpr();
993 const Expr *FalseExpr = CondOp->getFalseExpr();
998 diag(CondOp->getColonLoc(),
999 "'true' and 'false' expressions are equivalent");
1002 if (
const auto *Call = Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"call")) {
1003 const auto *OverloadedFunctionDecl = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
1004 if (!OverloadedFunctionDecl)
1010 diag(Call->getOperatorLoc(),
1011 "both sides of overloaded operator are equivalent");
1014 if (
const auto *NegateOperator =
1015 Result.Nodes.getNodeAs<UnaryOperator>(
"logical-bitwise-confusion")) {
1016 SourceLocation OperatorLoc = NegateOperator->getOperatorLoc();
1020 "ineffective logical negation operator used; did you mean '~'?");
1021 SourceLocation LogicalNotLocation = OperatorLoc.getLocWithOffset(1);
1023 if (!LogicalNotLocation.isMacroID())
1024 Diag << FixItHint::CreateReplacement(
1025 CharSourceRange::getCharRange(OperatorLoc, LogicalNotLocation),
"~");
1028 if (
const auto *BinaryAndExpr = Result.Nodes.getNodeAs<BinaryOperator>(
1029 "left-right-shift-confusion")) {
1030 const auto *ShiftingConst = Result.Nodes.getNodeAs<Expr>(
"shift-const");
1031 assert(ShiftingConst &&
"Expr* 'ShiftingConst' is nullptr!");
1032 APSInt ShiftingValue;
1034 if (!ShiftingConst->isIntegerConstantExpr(ShiftingValue, *Result.Context))
1037 const auto *AndConst = Result.Nodes.getNodeAs<Expr>(
"and-const");
1038 assert(AndConst &&
"Expr* 'AndCont' is nullptr!");
1040 if (!AndConst->isIntegerConstantExpr(AndValue, *Result.Context))
1046 if (floor(log2(AndValue.getExtValue())) >= ShiftingValue)
1049 auto Diag = diag(BinaryAndExpr->getOperatorLoc(),
1050 "ineffective bitwise and operation.");
1058 checkArithmeticExpr(Result);
1066 checkBitwiseExpr(Result);
1074 checkRelationalExpr(Result);
SourceLocation Loc
'#' location in the include directive
static bool exprEvaluatesToZero(BinaryOperatorKind Opcode, APSInt Value)
static ast_matchers::internal::Matcher< Expr > matchRelationalIntegerConstantExpr(StringRef Id)
static bool rangesFullyCoverDomain(BinaryOperatorKind OpcodeLHS, const APSInt &ValueLHS, BinaryOperatorKind OpcodeRHS, const APSInt &ValueRHS)
static bool areExprsFromDifferentMacros(const Expr *LhsExpr, const Expr *RhsExpr, const ASTContext *AstCtx)
static bool retrieveIntegerConstantExpr(const MatchFinder::MatchResult &Result, StringRef Id, APSInt &Value)
static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp, BinaryOperatorKind &MainOpcode, BinaryOperatorKind &SideOpcode, const Expr *&LhsConst, const Expr *&RhsConst, const ASTContext *AstCtx)
static bool rangeSubsumesRange(BinaryOperatorKind OpcodeLHS, const APSInt &ValueLHS, BinaryOperatorKind OpcodeRHS, const APSInt &ValueRHS)
static bool areEquivalentNameSpecifier(const NestedNameSpecifier *Left, const NestedNameSpecifier *Right)
static bool isNonConstReferenceType(QualType ParamType)
static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value)
static void transformSubToCanonicalAddExpr(BinaryOperatorKind &Opcode, APSInt &Value)
static bool exprEvaluatesToBitwiseNegatedZero(BinaryOperatorKind Opcode, APSInt Value)
static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx)
static bool incrementWithoutOverflow(const APSInt &Value, APSInt &Result)
static bool retrieveRelationalIntegerConstantExpr(const MatchFinder::MatchResult &Result, StringRef Id, const Expr *&OperandExpr, BinaryOperatorKind &Opcode, const Expr *&Symbol, APSInt &Value, const Expr *&ConstExpr)
static bool areEquivalentRanges(BinaryOperatorKind OpcodeLHS, const APSInt &ValueLHS, BinaryOperatorKind OpcodeRHS, const APSInt &ValueRHS)
static ast_matchers::internal::Matcher< Expr > matchSymbolicExpr(StringRef Id)
static bool canOverloadedOperatorArgsBeModified(const FunctionDecl *OperatorDecl, bool checkSecondParam)
static bool retrieveSymbolicExpr(const MatchFinder::MatchResult &Result, StringRef Id, const Expr *&SymExpr)
static bool areExclusiveRanges(BinaryOperatorKind OpcodeLHS, const APSInt &ValueLHS, BinaryOperatorKind OpcodeRHS, const APSInt &ValueRHS)
static bool areEquivalentExpr(const Expr *Left, const Expr *Right)
static bool retrieveBinOpIntegerConstantExpr(const MatchFinder::MatchResult &Result, StringRef Id, BinaryOperatorKind &Opcode, const Expr *&Symbol, APSInt &Value)
static const llvm::StringSet KnownBannedMacroNames
static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr, const Expr *&RhsExpr)
static ast_matchers::internal::Matcher< Expr > matchBinOpIntegerConstantExpr(StringRef Id)
static ast_matchers::internal::Matcher< Expr > matchIntegerConstantExpr(StringRef Id)
AST_MATCHER(VarDecl, isAsm)
AST_MATCHER_P(Expr, expandedByMacro, llvm::StringSet<>, Names)