10 #include "../utils/Matchers.h"
11 #include "../utils/OptionsUtils.h"
12 #include "clang/AST/ASTContext.h"
13 #include "clang/ASTMatchers/ASTMatchFinder.h"
14 #include "clang/Basic/LLVM.h"
15 #include "clang/Basic/SourceLocation.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Lex/Lexer.h"
18 #include "llvm/ADT/APInt.h"
19 #include "llvm/ADT/APSInt.h"
20 #include "llvm/ADT/FoldingSet.h"
21 #include "llvm/ADT/SmallBitVector.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/FormatVariadic.h"
39 static constexpr llvm::StringLiteral KnownBannedMacroNames[] = {
46 static bool incrementWithoutOverflow(
const APSInt &Value, APSInt &Result) {
49 return Value < Result;
52 static bool areEquivalentNameSpecifier(
const NestedNameSpecifier *Left,
53 const NestedNameSpecifier *Right) {
54 llvm::FoldingSetNodeID LeftID, RightID;
55 Left->Profile(LeftID);
56 Right->Profile(RightID);
57 return LeftID == RightID;
60 static bool areEquivalentExpr(
const Expr *Left,
const Expr *Right) {
68 if (
Left->getStmtClass() !=
Right->getStmtClass())
72 Expr::const_child_iterator LeftIter =
Left->child_begin();
73 Expr::const_child_iterator RightIter =
Right->child_begin();
74 while (LeftIter !=
Left->child_end() && RightIter !=
Right->child_end()) {
75 if (!areEquivalentExpr(dyn_cast_or_null<Expr>(*LeftIter),
76 dyn_cast_or_null<Expr>(*RightIter)))
81 if (LeftIter !=
Left->child_end() || RightIter !=
Right->child_end())
85 switch (
Left->getStmtClass()) {
89 case Stmt::CharacterLiteralClass:
90 return cast<CharacterLiteral>(Left)->getValue() ==
91 cast<CharacterLiteral>(Right)->getValue();
92 case Stmt::IntegerLiteralClass: {
93 llvm::APInt LeftLit = cast<IntegerLiteral>(Left)->getValue();
94 llvm::APInt RightLit = cast<IntegerLiteral>(Right)->getValue();
95 return LeftLit.getBitWidth() == RightLit.getBitWidth() &&
98 case Stmt::FloatingLiteralClass:
99 return cast<FloatingLiteral>(Left)->getValue().bitwiseIsEqual(
100 cast<FloatingLiteral>(Right)->getValue());
101 case Stmt::StringLiteralClass:
102 return cast<StringLiteral>(Left)->getBytes() ==
103 cast<StringLiteral>(Right)->getBytes();
104 case Stmt::CXXOperatorCallExprClass:
105 return cast<CXXOperatorCallExpr>(Left)->getOperator() ==
106 cast<CXXOperatorCallExpr>(Right)->getOperator();
107 case Stmt::DependentScopeDeclRefExprClass:
108 if (cast<DependentScopeDeclRefExpr>(Left)->getDeclName() !=
109 cast<DependentScopeDeclRefExpr>(Right)->getDeclName())
111 return areEquivalentNameSpecifier(
112 cast<DependentScopeDeclRefExpr>(Left)->getQualifier(),
113 cast<DependentScopeDeclRefExpr>(Right)->getQualifier());
114 case Stmt::DeclRefExprClass:
115 return cast<DeclRefExpr>(Left)->getDecl() ==
116 cast<DeclRefExpr>(Right)->getDecl();
117 case Stmt::MemberExprClass:
118 return cast<MemberExpr>(Left)->getMemberDecl() ==
119 cast<MemberExpr>(Right)->getMemberDecl();
120 case Stmt::CXXFoldExprClass:
121 return cast<CXXFoldExpr>(Left)->getOperator() ==
122 cast<CXXFoldExpr>(Right)->getOperator();
123 case Stmt::CXXFunctionalCastExprClass:
124 case Stmt::CStyleCastExprClass:
125 return cast<ExplicitCastExpr>(Left)->getTypeAsWritten() ==
126 cast<ExplicitCastExpr>(Right)->getTypeAsWritten();
127 case Stmt::CallExprClass:
128 case Stmt::ImplicitCastExprClass:
129 case Stmt::ArraySubscriptExprClass:
131 case Stmt::UnaryOperatorClass:
132 if (cast<UnaryOperator>(Left)->isIncrementDecrementOp())
134 return cast<UnaryOperator>(Left)->getOpcode() ==
135 cast<UnaryOperator>(Right)->getOpcode();
136 case Stmt::BinaryOperatorClass:
137 return cast<BinaryOperator>(Left)->getOpcode() ==
138 cast<BinaryOperator>(Right)->getOpcode();
139 case Stmt::UnaryExprOrTypeTraitExprClass:
140 const auto *LeftUnaryExpr =
141 cast<UnaryExprOrTypeTraitExpr>(Left);
142 const auto *RightUnaryExpr =
143 cast<UnaryExprOrTypeTraitExpr>(Right);
144 if (LeftUnaryExpr->isArgumentType() && RightUnaryExpr->isArgumentType())
145 return LeftUnaryExpr->getArgumentType() ==
146 RightUnaryExpr->getArgumentType();
147 else if (!LeftUnaryExpr->isArgumentType() &&
148 !RightUnaryExpr->isArgumentType())
149 return areEquivalentExpr(LeftUnaryExpr->getArgumentExpr(),
150 RightUnaryExpr->getArgumentExpr());
158 static bool areEquivalentRanges(BinaryOperatorKind OpcodeLHS,
159 const APSInt &ValueLHS,
160 BinaryOperatorKind OpcodeRHS,
161 const APSInt &ValueRHS) {
162 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
163 "Values must be ordered");
165 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0)
166 return OpcodeLHS == OpcodeRHS;
169 APSInt ValueLHS_plus1;
170 return ((OpcodeLHS == BO_LE && OpcodeRHS == BO_LT) ||
171 (OpcodeLHS == BO_GT && OpcodeRHS == BO_GE)) &&
172 incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
173 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0;
178 static bool areExclusiveRanges(BinaryOperatorKind OpcodeLHS,
179 const APSInt &ValueLHS,
180 BinaryOperatorKind OpcodeRHS,
181 const APSInt &ValueRHS) {
182 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
183 "Values must be ordered");
186 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
189 return OpcodeRHS == BO_NE || OpcodeRHS == BO_GT || OpcodeRHS == BO_LT;
191 return OpcodeRHS == BO_EQ;
193 return OpcodeRHS == BO_GT;
195 return OpcodeRHS == BO_LT;
197 return OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
199 return OpcodeRHS == BO_EQ || OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
206 if ((OpcodeLHS == BO_EQ || OpcodeLHS == BO_LT || OpcodeLHS == BO_LE) &&
207 (OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE))
211 APSInt ValueLHS_plus1;
212 if (OpcodeLHS == BO_GT && OpcodeRHS == BO_LT &&
213 incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
214 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
222 static bool rangesFullyCoverDomain(BinaryOperatorKind OpcodeLHS,
223 const APSInt &ValueLHS,
224 BinaryOperatorKind OpcodeRHS,
225 const APSInt &ValueRHS) {
226 assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
227 "Values must be ordered");
230 if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
233 return OpcodeRHS == BO_NE;
235 return OpcodeRHS == BO_EQ;
237 return OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
239 return OpcodeRHS == BO_GE;
241 return OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
243 return OpcodeRHS == BO_LE;
250 APSInt ValueLHS_plus1;
251 if (OpcodeLHS == BO_LE && OpcodeRHS == BO_GE &&
252 incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
253 APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
257 if ((OpcodeLHS == BO_GT || OpcodeLHS == BO_GE) &&
258 (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE))
263 if (OpcodeLHS == BO_NE && OpcodeRHS == BO_NE)
269 static bool rangeSubsumesRange(BinaryOperatorKind OpcodeLHS,
270 const APSInt &ValueLHS,
271 BinaryOperatorKind OpcodeRHS,
272 const APSInt &ValueRHS) {
273 int Comparison = APSInt::compareValues(ValueLHS, ValueRHS);
276 return OpcodeRHS == BO_EQ && Comparison == 0;
278 return (OpcodeRHS == BO_NE && Comparison == 0) ||
279 (OpcodeRHS == BO_EQ && Comparison != 0) ||
280 (OpcodeRHS == BO_LT && Comparison >= 0) ||
281 (OpcodeRHS == BO_LE && Comparison > 0) ||
282 (OpcodeRHS == BO_GT && Comparison <= 0) ||
283 (OpcodeRHS == BO_GE && Comparison < 0);
286 return ((OpcodeRHS == BO_LT && Comparison >= 0) ||
287 (OpcodeRHS == BO_LE && Comparison > 0) ||
288 (OpcodeRHS == BO_EQ && Comparison > 0));
290 return ((OpcodeRHS == BO_GT && Comparison <= 0) ||
291 (OpcodeRHS == BO_GE && Comparison < 0) ||
292 (OpcodeRHS == BO_EQ && Comparison < 0));
294 return (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE || OpcodeRHS == BO_EQ) &&
297 return (OpcodeRHS == BO_GT || OpcodeRHS == BO_GE || OpcodeRHS == BO_EQ) &&
304 static void transformSubToCanonicalAddExpr(BinaryOperatorKind &Opcode,
306 if (Opcode == BO_Sub) {
313 static OverloadedOperatorKind getOp(
const BinaryOperator *Op) {
314 return BinaryOperator::getOverloadedOperator(Op->getOpcode());
317 static OverloadedOperatorKind getOp(
const CXXOperatorCallExpr *Op) {
318 if (Op->getNumArgs() != 2)
320 return Op->getOperator();
323 static std::pair<const Expr *, const Expr *>
324 getOperands(
const BinaryOperator *Op) {
325 return {Op->getLHS()->IgnoreParenImpCasts(),
326 Op->getRHS()->IgnoreParenImpCasts()};
329 static std::pair<const Expr *, const Expr *>
330 getOperands(
const CXXOperatorCallExpr *Op) {
331 return {Op->getArg(0)->IgnoreParenImpCasts(),
332 Op->getArg(1)->IgnoreParenImpCasts()};
335 template <
typename TExpr>
336 static const TExpr *checkOpKind(
const Expr *TheExpr,
337 OverloadedOperatorKind OpKind) {
338 const auto *AsTExpr = dyn_cast_or_null<TExpr>(TheExpr);
339 if (AsTExpr && getOp(AsTExpr) == OpKind)
347 template <
typename TExpr,
unsigned N>
348 static bool collectOperands(
const Expr *Part,
349 SmallVector<const Expr *, N> &AllOperands,
350 OverloadedOperatorKind OpKind) {
351 if (
const auto *BinOp = checkOpKind<TExpr>(Part, OpKind)) {
352 const std::pair<const Expr *, const Expr *> Operands = getOperands(BinOp);
353 if (areEquivalentExpr(Operands.first, Operands.second))
355 return collectOperands<TExpr>(Operands.first, AllOperands, OpKind) ||
356 collectOperands<TExpr>(Operands.second, AllOperands, OpKind);
359 AllOperands.push_back(Part);
363 template <
typename TExpr>
364 static bool hasSameOperatorParent(
const Expr *TheExpr,
365 OverloadedOperatorKind OpKind,
366 ASTContext &Context) {
368 const DynTypedNodeList
Parents = Context.getParents(*TheExpr);
369 for (ast_type_traits::DynTypedNode DynParent : Parents) {
370 if (
const auto *
Parent = DynParent.get<Expr>()) {
371 bool Skip = isa<ParenExpr>(
Parent) || isa<ImplicitCastExpr>(
Parent) ||
373 isa<MaterializeTemporaryExpr>(
Parent);
374 if (Skip && hasSameOperatorParent<TExpr>(
Parent, OpKind, Context))
376 if (checkOpKind<TExpr>(
Parent, OpKind))
384 template <
typename TExpr>
386 markDuplicateOperands(
const TExpr *TheExpr,
387 ast_matchers::internal::BoundNodesTreeBuilder *
Builder,
388 ASTContext &Context) {
389 const OverloadedOperatorKind OpKind = getOp(TheExpr);
390 if (OpKind == OO_None)
394 const std::pair<const Expr *, const Expr *> Operands = getOperands(TheExpr);
395 if (!(checkOpKind<TExpr>(Operands.first, OpKind) ||
396 checkOpKind<TExpr>(Operands.second, OpKind)))
401 if (hasSameOperatorParent<TExpr>(TheExpr, OpKind, Context))
404 SmallVector<const Expr *, 4> AllOperands;
405 if (collectOperands<TExpr>(Operands.first, AllOperands, OpKind))
407 if (collectOperands<TExpr>(Operands.second, AllOperands, OpKind))
409 size_t NumOperands = AllOperands.size();
410 llvm::SmallBitVector Duplicates(NumOperands);
411 for (
size_t I = 0; I < NumOperands; I++) {
414 bool FoundDuplicates =
false;
416 for (
size_t J = I + 1; J < NumOperands; J++) {
417 if (AllOperands[J]->HasSideEffects(Context))
420 if (areEquivalentExpr(AllOperands[I], AllOperands[J])) {
421 FoundDuplicates =
true;
424 SmallString<11>(llvm::formatv(
"duplicate{0}", J)),
425 ast_type_traits::DynTypedNode::create(*AllOperands[J]));
431 SmallString<11>(llvm::formatv(
"duplicate{0}", I)),
432 ast_type_traits::DynTypedNode::create(*AllOperands[I]));
435 return Duplicates.any();
439 if (Node.isInstantiationDependent())
441 return Node.isIntegerConstantExpr(Finder->getASTContext());
444 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
445 return areEquivalentExpr(Node.getLHS(), Node.getRHS());
448 AST_MATCHER(BinaryOperator, nestedOperandsAreEquivalent) {
449 return markDuplicateOperands(&Node,
Builder, Finder->getASTContext());
452 AST_MATCHER(ConditionalOperator, expressionsAreEquivalent) {
453 return areEquivalentExpr(Node.getTrueExpr(), Node.getFalseExpr());
457 return Node.getNumArgs() == 2 &&
458 areEquivalentExpr(Node.getArg(0), Node.getArg(1));
461 AST_MATCHER(CXXOperatorCallExpr, nestedParametersAreEquivalent) {
462 return markDuplicateOperands(&Node,
Builder, Finder->getASTContext());
465 AST_MATCHER(BinaryOperator, binaryOperatorIsInMacro) {
466 return Node.getOperatorLoc().isMacroID();
469 AST_MATCHER(ConditionalOperator, conditionalOperatorIsInMacro) {
470 return Node.getQuestionLoc().isMacroID() || Node.getColonLoc().isMacroID();
473 AST_MATCHER(Expr, isMacro) {
return Node.getExprLoc().isMacroID(); }
475 AST_MATCHER_P(Expr, expandedByMacro, ArrayRef<llvm::StringLiteral>, Names) {
476 const SourceManager &SM = Finder->getASTContext().getSourceManager();
477 const LangOptions &LO = Finder->getASTContext().getLangOpts();
478 SourceLocation
Loc = Node.getExprLoc();
479 while (
Loc.isMacroID()) {
480 StringRef MacroName = Lexer::getImmediateMacroName(
Loc, SM, LO);
481 if (llvm::is_contained(Names, MacroName))
483 Loc = SM.getImmediateMacroCallerLoc(
Loc);
489 static ast_matchers::internal::Matcher<Expr>
490 matchIntegerConstantExpr(StringRef Id) {
491 std::string CstId = (Id +
"-const").str();
492 return expr(isIntegerConstantExpr()).bind(CstId);
498 static bool retrieveIntegerConstantExpr(
const MatchFinder::MatchResult &Result,
499 StringRef Id, APSInt &Value,
500 const Expr *&ConstExpr) {
501 std::string CstId = (Id +
"-const").str();
502 ConstExpr = Result.Nodes.getNodeAs<Expr>(CstId);
503 return ConstExpr && ConstExpr->isIntegerConstantExpr(Value, *Result.Context);
507 static bool retrieveIntegerConstantExpr(
const MatchFinder::MatchResult &Result,
508 StringRef Id, APSInt &Value) {
509 const Expr *ConstExpr =
nullptr;
510 return retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr);
515 static ast_matchers::internal::Matcher<Expr> matchSymbolicExpr(StringRef Id) {
516 std::string SymId = (Id +
"-sym").str();
517 return ignoringParenImpCasts(
518 expr(unless(isIntegerConstantExpr())).bind(SymId));
523 static bool retrieveSymbolicExpr(
const MatchFinder::MatchResult &Result,
524 StringRef Id,
const Expr *&SymExpr) {
525 std::string SymId = (Id +
"-sym").str();
526 if (
const auto *Node = Result.Nodes.getNodeAs<Expr>(SymId)) {
535 static ast_matchers::internal::Matcher<Expr>
536 matchBinOpIntegerConstantExpr(StringRef Id) {
537 const auto BinOpCstExpr =
538 expr(anyOf(binaryOperator(hasAnyOperatorName(
"+",
"|",
"&"),
539 hasOperands(matchSymbolicExpr(Id),
540 matchIntegerConstantExpr(Id))),
541 binaryOperator(hasOperatorName(
"-"),
542 hasLHS(matchSymbolicExpr(Id)),
543 hasRHS(matchIntegerConstantExpr(Id)))))
545 return ignoringParenImpCasts(BinOpCstExpr);
551 retrieveBinOpIntegerConstantExpr(
const MatchFinder::MatchResult &Result,
552 StringRef Id, BinaryOperatorKind &Opcode,
553 const Expr *&Symbol, APSInt &Value) {
554 if (
const auto *BinExpr = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
555 Opcode = BinExpr->getOpcode();
556 return retrieveSymbolicExpr(Result, Id, Symbol) &&
557 retrieveIntegerConstantExpr(Result, Id, Value);
563 static ast_matchers::internal::Matcher<Expr>
564 matchRelationalIntegerConstantExpr(StringRef Id) {
565 std::string CastId = (Id +
"-cast").str();
566 std::string SwapId = (Id +
"-swap").str();
567 std::string NegateId = (Id +
"-negate").str();
568 std::string OverloadId = (Id +
"-overload").str();
570 const auto RelationalExpr = ignoringParenImpCasts(binaryOperator(
571 isComparisonOperator(), expr().bind(Id),
572 anyOf(allOf(hasLHS(matchSymbolicExpr(Id)),
573 hasRHS(matchIntegerConstantExpr(Id))),
574 allOf(hasLHS(matchIntegerConstantExpr(Id)),
575 hasRHS(matchSymbolicExpr(Id)), expr().bind(SwapId)))));
579 const auto CastExpr =
580 implicitCastExpr(hasCastKind(CK_IntegralToBoolean),
581 hasSourceExpression(matchSymbolicExpr(Id)))
584 const auto NegateRelationalExpr =
585 unaryOperator(hasOperatorName(
"!"),
586 hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))
590 const auto NegateNegateRelationalExpr =
591 unaryOperator(hasOperatorName(
"!"),
592 hasUnaryOperand(unaryOperator(
593 hasOperatorName(
"!"),
594 hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))));
596 const auto OverloadedOperatorExpr =
598 hasAnyOverloadedOperatorName(
"==",
"!=",
"<",
"<=",
">",
">="),
600 unless(isMacro()), unless(isInTemplateInstantiation()))
603 return anyOf(RelationalExpr, CastExpr, NegateRelationalExpr,
604 NegateNegateRelationalExpr, OverloadedOperatorExpr);
609 static bool isNonConstReferenceType(QualType ParamType) {
610 return ParamType->isReferenceType() &&
611 !ParamType.getNonReferenceType().isConstQualified();
621 canOverloadedOperatorArgsBeModified(
const CXXOperatorCallExpr *OperatorCall,
622 bool checkSecondParam) {
623 const auto *OperatorDecl =
624 dyn_cast_or_null<FunctionDecl>(OperatorCall->getCalleeDecl());
630 unsigned ParamCount = OperatorDecl->getNumParams();
635 if (ParamCount == 1 &&
636 !OperatorDecl->getType()->castAs<FunctionType>()->isConst())
639 if (isNonConstReferenceType(OperatorDecl->getParamDecl(0)->getType()))
642 return checkSecondParam && ParamCount == 2 &&
643 isNonConstReferenceType(OperatorDecl->getParamDecl(1)->getType());
648 static bool retrieveRelationalIntegerConstantExpr(
649 const MatchFinder::MatchResult &Result, StringRef Id,
650 const Expr *&OperandExpr, BinaryOperatorKind &Opcode,
const Expr *&Symbol,
651 APSInt &Value,
const Expr *&ConstExpr) {
652 std::string CastId = (Id +
"-cast").str();
653 std::string SwapId = (Id +
"-swap").str();
654 std::string NegateId = (Id +
"-negate").str();
655 std::string OverloadId = (Id +
"-overload").str();
657 if (
const auto *Bin = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
659 Opcode = Bin->getOpcode();
662 if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr))
664 }
else if (
const auto *Cast = Result.Nodes.getNodeAs<CastExpr>(CastId)) {
668 Value = APSInt(32,
false);
669 }
else if (
const auto *OverloadedOperatorExpr =
670 Result.Nodes.getNodeAs<CXXOperatorCallExpr>(OverloadId)) {
671 if (canOverloadedOperatorArgsBeModified(OverloadedOperatorExpr,
false))
674 if (
const auto *Arg = OverloadedOperatorExpr->getArg(1)) {
675 if (!Arg->isValueDependent() &&
676 !Arg->isIntegerConstantExpr(Value, *Result.Context))
679 Symbol = OverloadedOperatorExpr->getArg(0);
680 OperandExpr = OverloadedOperatorExpr;
681 Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());
683 return BinaryOperator::isComparisonOp(Opcode);
688 if (!retrieveSymbolicExpr(Result, Id, Symbol))
691 if (Result.Nodes.getNodeAs<Expr>(SwapId))
692 Opcode = BinaryOperator::reverseComparisonOp(Opcode);
693 if (Result.Nodes.getNodeAs<Expr>(NegateId))
694 Opcode = BinaryOperator::negateComparisonOp(Opcode);
699 static bool areSidesBinaryConstExpressions(
const BinaryOperator *&BinOp,
const ASTContext *AstCtx) {
700 const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS());
701 const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS());
703 if (!LhsBinOp || !RhsBinOp)
706 auto IsIntegerConstantExpr = [AstCtx](
const Expr *
E) {
707 return !
E->isValueDependent() &&
E->isIntegerConstantExpr(*AstCtx);
710 if ((IsIntegerConstantExpr(LhsBinOp->getLHS()) ||
711 IsIntegerConstantExpr(LhsBinOp->getRHS())) &&
712 (IsIntegerConstantExpr(RhsBinOp->getLHS()) ||
713 IsIntegerConstantExpr(RhsBinOp->getRHS())))
721 static bool retrieveConstExprFromBothSides(
const BinaryOperator *&BinOp,
722 BinaryOperatorKind &MainOpcode,
723 BinaryOperatorKind &SideOpcode,
724 const Expr *&LhsConst,
725 const Expr *&RhsConst,
726 const ASTContext *AstCtx) {
727 assert(areSidesBinaryConstExpressions(BinOp, AstCtx) &&
728 "Both sides of binary operator must be constant expressions!");
730 MainOpcode = BinOp->getOpcode();
732 const auto *BinOpLhs = cast<BinaryOperator>(BinOp->getLHS());
733 const auto *BinOpRhs = cast<BinaryOperator>(BinOp->getRHS());
735 auto IsIntegerConstantExpr = [AstCtx](
const Expr *
E) {
736 return !
E->isValueDependent() &&
E->isIntegerConstantExpr(*AstCtx);
739 LhsConst = IsIntegerConstantExpr(BinOpLhs->getLHS()) ? BinOpLhs->getLHS()
740 : BinOpLhs->getRHS();
741 RhsConst = IsIntegerConstantExpr(BinOpRhs->getLHS()) ? BinOpRhs->getLHS()
742 : BinOpRhs->getRHS();
744 if (!LhsConst || !RhsConst)
747 assert(BinOpLhs->getOpcode() == BinOpRhs->getOpcode() &&
748 "Sides of the binary operator must be equivalent expressions!");
750 SideOpcode = BinOpLhs->getOpcode();
755 static bool isSameRawIdentifierToken(
const Token &T1,
const Token &T2,
756 const SourceManager &SM) {
757 if (T1.getKind() != T2.getKind())
759 if (T1.isNot(tok::raw_identifier))
761 if (T1.getLength() != T2.getLength())
763 return StringRef(SM.getCharacterData(T1.getLocation()), T1.getLength()) ==
764 StringRef(SM.getCharacterData(T2.getLocation()), T2.getLength());
767 bool isTokAtEndOfExpr(SourceRange ExprSR, Token T,
const SourceManager &SM) {
768 return SM.getExpansionLoc(ExprSR.getEnd()) == T.getLocation();
774 static bool areExprsFromDifferentMacros(
const Expr *LhsExpr,
776 const ASTContext *AstCtx) {
777 if (!LhsExpr || !RhsExpr)
779 SourceRange Lsr = LhsExpr->getSourceRange();
780 SourceRange Rsr = RhsExpr->getSourceRange();
781 if (!Lsr.getBegin().isMacroID() || !Rsr.getBegin().isMacroID())
784 const SourceManager &SM = AstCtx->getSourceManager();
785 const LangOptions &LO = AstCtx->getLangOpts();
787 std::pair<FileID, unsigned> LsrLocInfo =
788 SM.getDecomposedLoc(SM.getExpansionLoc(Lsr.getBegin()));
789 std::pair<FileID, unsigned> RsrLocInfo =
790 SM.getDecomposedLoc(SM.getExpansionLoc(Rsr.getBegin()));
791 const llvm::MemoryBuffer *MB = SM.getBuffer(LsrLocInfo.first);
793 const char *LTokenPos = MB->getBufferStart() + LsrLocInfo.second;
794 const char *RTokenPos = MB->getBufferStart() + RsrLocInfo.second;
795 Lexer LRawLex(SM.getLocForStartOfFile(LsrLocInfo.first), LO,
796 MB->getBufferStart(), LTokenPos, MB->getBufferEnd());
797 Lexer RRawLex(SM.getLocForStartOfFile(RsrLocInfo.first), LO,
798 MB->getBufferStart(), RTokenPos, MB->getBufferEnd());
802 LRawLex.LexFromRawLexer(LTok);
803 RRawLex.LexFromRawLexer(RTok);
804 }
while (!LTok.is(tok::eof) && !RTok.is(tok::eof) &&
805 isSameRawIdentifierToken(LTok, RTok, SM) &&
806 !isTokAtEndOfExpr(Lsr, LTok, SM) &&
807 !isTokAtEndOfExpr(Rsr, RTok, SM));
808 return (!isTokAtEndOfExpr(Lsr, LTok, SM) ||
809 !isTokAtEndOfExpr(Rsr, RTok, SM)) ||
810 !isSameRawIdentifierToken(LTok, RTok, SM);
813 static bool areExprsMacroAndNonMacro(
const Expr *&LhsExpr,
814 const Expr *&RhsExpr) {
815 if (!LhsExpr || !RhsExpr)
818 SourceLocation LhsLoc = LhsExpr->getExprLoc();
819 SourceLocation RhsLoc = RhsExpr->getExprLoc();
821 return LhsLoc.isMacroID() != RhsLoc.isMacroID();
825 void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
826 const auto AnyLiteralExpr = ignoringParenImpCasts(
827 anyOf(cxxBoolLiteral(), characterLiteral(), integerLiteral()));
829 const auto BannedIntegerLiteral =
830 integerLiteral(expandedByMacro(KnownBannedMacroNames));
834 traverse(ast_type_traits::TK_AsIs,
836 anyOf(isComparisonOperator(),
837 hasAnyOperatorName(
"-",
"/",
"%",
"|",
"&",
"^",
"&&",
839 operandsAreEquivalent(),
841 unless(isInTemplateInstantiation()),
842 unless(binaryOperatorIsInMacro()),
843 unless(hasType(realFloatingPointType())),
844 unless(hasEitherOperand(hasType(realFloatingPointType()))),
845 unless(hasLHS(AnyLiteralExpr)),
846 unless(hasDescendant(BannedIntegerLiteral)))
853 binaryOperator(hasAnyOperatorName(
"|",
"&",
"||",
"&&",
"^"),
854 nestedOperandsAreEquivalent(),
856 unless(isInTemplateInstantiation()),
857 unless(binaryOperatorIsInMacro()),
859 unless(hasDescendant(BannedIntegerLiteral)))
860 .bind(
"nested-duplicates"),
865 traverse(ast_type_traits::TK_AsIs,
866 conditionalOperator(expressionsAreEquivalent(),
868 unless(conditionalOperatorIsInMacro()),
869 unless(isInTemplateInstantiation()))
875 traverse(ast_type_traits::TK_AsIs,
877 hasAnyOverloadedOperatorName(
"-",
"/",
"%",
"|",
"&",
"^",
878 "==",
"!=",
"<",
"<=",
">",
879 ">=",
"&&",
"||",
"="),
880 parametersAreEquivalent(),
882 unless(isMacro()), unless(isInTemplateInstantiation()))
889 hasAnyOverloadedOperatorName(
"|",
"&",
"||",
"&&",
"^"),
890 nestedParametersAreEquivalent(), argumentCountIs(2),
892 unless(isMacro()), unless(isInTemplateInstantiation()))
893 .bind(
"nested-duplicates"),
898 traverse(ast_type_traits::TK_AsIs,
900 hasImplicitDestinationType(isInteger()),
902 hasOperatorName(
"!"),
903 hasUnaryOperand(ignoringParenImpCasts(binaryOperator(
904 hasAnyOperatorName(
"|",
"&"),
906 binaryOperator(hasAnyOperatorName(
"|",
"&")),
908 hasRHS(integerLiteral())))))
909 .bind(
"logical-bitwise-confusion")))),
915 ast_type_traits::TK_AsIs,
917 hasOperatorName(
"&"),
919 ignoringParenImpCasts(
920 binaryOperator(hasOperatorName(
"<<"),
921 hasRHS(ignoringParenImpCasts(
922 integerLiteral().bind(
"shift-const"))))),
923 ignoringParenImpCasts(integerLiteral().bind(
"and-const"))))
924 .bind(
"left-right-shift-confusion")),
933 const auto BinOpCstLeft = matchBinOpIntegerConstantExpr(
"lhs");
934 const auto BinOpCstRight = matchBinOpIntegerConstantExpr(
"rhs");
935 const auto CstRight = matchIntegerConstantExpr(
"rhs");
936 const auto SymRight = matchSymbolicExpr(
"rhs");
939 Finder->addMatcher(traverse(ast_type_traits::TK_AsIs,
940 binaryOperator(isComparisonOperator(),
941 hasOperands(BinOpCstLeft,
943 .bind(
"binop-const-compare-to-const")),
949 ast_type_traits::TK_AsIs,
950 binaryOperator(isComparisonOperator(),
951 anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)),
952 allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft))))
953 .bind(
"binop-const-compare-to-sym")),
958 traverse(ast_type_traits::TK_AsIs,
959 binaryOperator(isComparisonOperator(), hasLHS(BinOpCstLeft),
960 hasRHS(BinOpCstRight),
962 unless(operandsAreEquivalent()))
963 .bind(
"binop-const-compare-to-binop-const")),
971 const auto ComparisonLeft = matchRelationalIntegerConstantExpr(
"lhs");
972 const auto ComparisonRight = matchRelationalIntegerConstantExpr(
"rhs");
974 traverse(ast_type_traits::TK_AsIs,
975 binaryOperator(hasAnyOperatorName(
"||",
"&&"),
976 hasLHS(ComparisonLeft), hasRHS(ComparisonRight),
978 unless(operandsAreEquivalent()))
979 .bind(
"comparisons-of-symbol-and-const")),
983 void RedundantExpressionCheck::checkArithmeticExpr(
984 const MatchFinder::MatchResult &Result) {
985 APSInt LhsValue, RhsValue;
986 const Expr *LhsSymbol =
nullptr, *RhsSymbol =
nullptr;
987 BinaryOperatorKind LhsOpcode, RhsOpcode;
989 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
990 "binop-const-compare-to-sym")) {
991 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
992 if (!retrieveBinOpIntegerConstantExpr(Result,
"lhs", LhsOpcode, LhsSymbol,
994 !retrieveSymbolicExpr(Result,
"rhs", RhsSymbol) ||
995 !areEquivalentExpr(LhsSymbol, RhsSymbol))
999 if (LhsOpcode == BO_Add || LhsOpcode == BO_Sub) {
1000 if ((LhsValue != 0 && Opcode == BO_EQ) ||
1001 (LhsValue == 0 && Opcode == BO_NE))
1002 diag(ComparisonOperator->getOperatorLoc(),
1003 "logical expression is always false");
1004 else if ((LhsValue == 0 && Opcode == BO_EQ) ||
1005 (LhsValue != 0 && Opcode == BO_NE))
1006 diag(ComparisonOperator->getOperatorLoc(),
1007 "logical expression is always true");
1009 }
else if (
const auto *ComparisonOperator =
1010 Result.Nodes.getNodeAs<BinaryOperator>(
1011 "binop-const-compare-to-binop-const")) {
1012 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
1014 if (!retrieveBinOpIntegerConstantExpr(Result,
"lhs", LhsOpcode, LhsSymbol,
1016 !retrieveBinOpIntegerConstantExpr(Result,
"rhs", RhsOpcode, RhsSymbol,
1018 !areEquivalentExpr(LhsSymbol, RhsSymbol))
1021 transformSubToCanonicalAddExpr(LhsOpcode, LhsValue);
1022 transformSubToCanonicalAddExpr(RhsOpcode, RhsValue);
1025 if (LhsOpcode == BO_Add && RhsOpcode == BO_Add) {
1026 if ((Opcode == BO_EQ && APSInt::compareValues(LhsValue, RhsValue) == 0) ||
1027 (Opcode == BO_NE && APSInt::compareValues(LhsValue, RhsValue) != 0)) {
1028 diag(ComparisonOperator->getOperatorLoc(),
1029 "logical expression is always true");
1030 }
else if ((Opcode == BO_EQ &&
1031 APSInt::compareValues(LhsValue, RhsValue) != 0) ||
1033 APSInt::compareValues(LhsValue, RhsValue) == 0)) {
1034 diag(ComparisonOperator->getOperatorLoc(),
1035 "logical expression is always false");
1042 return (Opcode == BO_And || Opcode == BO_AndAssign) && Value == 0;
1047 return (Opcode == BO_Or || Opcode == BO_OrAssign) && ~Value == 0;
1051 return ((Opcode == BO_Or || Opcode == BO_OrAssign) && Value == 0) ||
1052 ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
1056 void RedundantExpressionCheck::checkBitwiseExpr(
1057 const MatchFinder::MatchResult &Result) {
1058 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
1059 "binop-const-compare-to-const")) {
1060 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
1062 APSInt LhsValue, RhsValue;
1063 const Expr *LhsSymbol =
nullptr;
1064 BinaryOperatorKind LhsOpcode;
1065 if (!retrieveBinOpIntegerConstantExpr(Result,
"lhs", LhsOpcode, LhsSymbol,
1067 !retrieveIntegerConstantExpr(Result,
"rhs", RhsValue))
1070 uint64_t LhsConstant = LhsValue.getZExtValue();
1071 uint64_t RhsConstant = RhsValue.getZExtValue();
1072 SourceLocation
Loc = ComparisonOperator->getOperatorLoc();
1075 if (LhsOpcode == BO_And && (LhsConstant & RhsConstant) != RhsConstant) {
1076 if (Opcode == BO_EQ)
1077 diag(
Loc,
"logical expression is always false");
1078 else if (Opcode == BO_NE)
1079 diag(
Loc,
"logical expression is always true");
1083 if (LhsOpcode == BO_Or && (LhsConstant | RhsConstant) != RhsConstant) {
1084 if (Opcode == BO_EQ)
1085 diag(
Loc,
"logical expression is always false");
1086 else if (Opcode == BO_NE)
1087 diag(
Loc,
"logical expression is always true");
1089 }
else if (
const auto *IneffectiveOperator =
1090 Result.Nodes.getNodeAs<BinaryOperator>(
1091 "ineffective-bitwise")) {
1093 const Expr *Sym =
nullptr, *ConstExpr =
nullptr;
1095 if (!retrieveSymbolicExpr(Result,
"ineffective-bitwise", Sym) ||
1096 !retrieveIntegerConstantExpr(Result,
"ineffective-bitwise", Value,
1100 if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
1103 SourceLocation
Loc = IneffectiveOperator->getOperatorLoc();
1105 BinaryOperatorKind Opcode = IneffectiveOperator->getOpcode();
1107 diag(
Loc,
"expression always evaluates to 0");
1109 SourceRange ConstExprRange(ConstExpr->getBeginLoc(),
1110 ConstExpr->getEndLoc());
1111 StringRef ConstExprText = Lexer::getSourceText(
1112 CharSourceRange::getTokenRange(ConstExprRange), *Result.SourceManager,
1113 Result.Context->getLangOpts());
1115 diag(
Loc,
"expression always evaluates to '%0'") << ConstExprText;
1118 SourceRange SymExprRange(Sym->getBeginLoc(), Sym->getEndLoc());
1120 StringRef ExprText = Lexer::getSourceText(
1121 CharSourceRange::getTokenRange(SymExprRange), *Result.SourceManager,
1122 Result.Context->getLangOpts());
1124 diag(
Loc,
"expression always evaluates to '%0'") << ExprText;
1129 void RedundantExpressionCheck::checkRelationalExpr(
1130 const MatchFinder::MatchResult &Result) {
1131 if (
const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
1132 "comparisons-of-symbol-and-const")) {
1135 BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
1137 const Expr *LhsExpr =
nullptr, *RhsExpr =
nullptr;
1138 const Expr *LhsSymbol =
nullptr, *RhsSymbol =
nullptr;
1139 const Expr *LhsConst =
nullptr, *RhsConst =
nullptr;
1140 BinaryOperatorKind LhsOpcode, RhsOpcode;
1141 APSInt LhsValue, RhsValue;
1143 if (!retrieveRelationalIntegerConstantExpr(
1144 Result,
"lhs", LhsExpr, LhsOpcode, LhsSymbol, LhsValue, LhsConst) ||
1145 !retrieveRelationalIntegerConstantExpr(
1146 Result,
"rhs", RhsExpr, RhsOpcode, RhsSymbol, RhsValue, RhsConst) ||
1147 !areEquivalentExpr(LhsSymbol, RhsSymbol))
1151 if (APSInt::compareValues(LhsValue, RhsValue) > 0) {
1152 std::swap(LhsExpr, RhsExpr);
1153 std::swap(LhsValue, RhsValue);
1154 std::swap(LhsSymbol, RhsSymbol);
1155 std::swap(LhsOpcode, RhsOpcode);
1159 if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
1160 areExprsMacroAndNonMacro(LhsConst, RhsConst))
1163 if ((Opcode == BO_LAnd || Opcode == BO_LOr) &&
1164 areEquivalentRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
1165 diag(ComparisonOperator->getOperatorLoc(),
1166 "equivalent expression on both sides of logical operator");
1170 if (Opcode == BO_LAnd) {
1171 if (areExclusiveRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
1172 diag(ComparisonOperator->getOperatorLoc(),
1173 "logical expression is always false");
1174 }
else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
1175 diag(LhsExpr->getExprLoc(),
"expression is redundant");
1176 }
else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
1177 diag(RhsExpr->getExprLoc(),
"expression is redundant");
1181 if (Opcode == BO_LOr) {
1182 if (rangesFullyCoverDomain(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
1183 diag(ComparisonOperator->getOperatorLoc(),
1184 "logical expression is always true");
1185 }
else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
1186 diag(RhsExpr->getExprLoc(),
"expression is redundant");
1187 }
else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
1188 diag(LhsExpr->getExprLoc(),
"expression is redundant");
1194 void RedundantExpressionCheck::check(
const MatchFinder::MatchResult &Result) {
1195 if (
const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>(
"binary")) {
1198 if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
1199 const Expr *LhsConst =
nullptr, *RhsConst =
nullptr;
1200 BinaryOperatorKind MainOpcode, SideOpcode;
1202 if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
1203 LhsConst, RhsConst, Result.Context))
1206 if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
1207 areExprsMacroAndNonMacro(LhsConst, RhsConst))
1211 diag(BinOp->getOperatorLoc(),
"both sides of operator are equivalent");
1214 if (
const auto *CondOp =
1215 Result.Nodes.getNodeAs<ConditionalOperator>(
"cond")) {
1216 const Expr *TrueExpr = CondOp->getTrueExpr();
1217 const Expr *FalseExpr = CondOp->getFalseExpr();
1219 if (areExprsFromDifferentMacros(TrueExpr, FalseExpr, Result.Context) ||
1220 areExprsMacroAndNonMacro(TrueExpr, FalseExpr))
1222 diag(CondOp->getColonLoc(),
1223 "'true' and 'false' expressions are equivalent");
1226 if (
const auto *Call = Result.Nodes.getNodeAs<CXXOperatorCallExpr>(
"call")) {
1227 if (canOverloadedOperatorArgsBeModified(Call,
true))
1230 diag(Call->getOperatorLoc(),
1231 "both sides of overloaded operator are equivalent");
1234 if (
const auto *Op = Result.Nodes.getNodeAs<Expr>(
"nested-duplicates")) {
1235 const auto *Call = dyn_cast<CXXOperatorCallExpr>(Op);
1236 if (Call && canOverloadedOperatorArgsBeModified(Call,
true))
1240 Call ?
"overloaded operator has equivalent nested operands"
1241 :
"operator has equivalent nested operands";
1243 const auto Diag = diag(Op->getExprLoc(),
Message);
1244 for (
const auto &KeyValue : Result.Nodes.getMap()) {
1245 if (StringRef(KeyValue.first).startswith(
"duplicate"))
1246 Diag << KeyValue.second.getSourceRange();
1250 if (
const auto *NegateOperator =
1251 Result.Nodes.getNodeAs<UnaryOperator>(
"logical-bitwise-confusion")) {
1252 SourceLocation OperatorLoc = NegateOperator->getOperatorLoc();
1256 "ineffective logical negation operator used; did you mean '~'?");
1257 SourceLocation LogicalNotLocation = OperatorLoc.getLocWithOffset(1);
1259 if (!LogicalNotLocation.isMacroID())
1260 Diag << FixItHint::CreateReplacement(
1261 CharSourceRange::getCharRange(OperatorLoc, LogicalNotLocation),
"~");
1264 if (
const auto *BinaryAndExpr = Result.Nodes.getNodeAs<BinaryOperator>(
1265 "left-right-shift-confusion")) {
1266 const auto *ShiftingConst = Result.Nodes.getNodeAs<Expr>(
"shift-const");
1267 assert(ShiftingConst &&
"Expr* 'ShiftingConst' is nullptr!");
1268 APSInt ShiftingValue;
1270 if (!ShiftingConst->isIntegerConstantExpr(ShiftingValue, *Result.Context))
1273 const auto *AndConst = Result.Nodes.getNodeAs<Expr>(
"and-const");
1274 assert(AndConst &&
"Expr* 'AndCont' is nullptr!");
1276 if (!AndConst->isIntegerConstantExpr(AndValue, *Result.Context))
1282 if (AndValue.getActiveBits() > ShiftingValue)
1285 auto Diag = diag(BinaryAndExpr->getOperatorLoc(),
1286 "ineffective bitwise and operation");
1294 checkArithmeticExpr(Result);
1302 checkBitwiseExpr(Result);
1310 checkRelationalExpr(Result);