clang-tools  6.0.0
RedundantExpressionCheck.cpp
Go to the documentation of this file.
1 //===--- RedundantExpressionCheck.cpp - clang-tidy-------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
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"
23 #include <algorithm>
24 #include <cassert>
25 #include <cmath>
26 #include <cstdint>
27 #include <string>
28 #include <vector>
29 
30 using namespace clang::ast_matchers;
31 using namespace clang::tidy::matchers;
32 
33 namespace clang {
34 namespace tidy {
35 namespace misc {
36 
37 namespace {
38 using llvm::APSInt;
39 } // namespace
40 
41 static const llvm::StringSet<> KnownBannedMacroNames = {"EAGAIN", "EWOULDBLOCK",
42  "SIGCLD", "SIGCHLD"};
43 
44 static bool incrementWithoutOverflow(const APSInt &Value, APSInt &Result) {
45  Result = Value;
46  ++Result;
47  return Value < Result;
48 }
49 
50 static bool areEquivalentNameSpecifier(const NestedNameSpecifier *Left,
51  const NestedNameSpecifier *Right) {
52  llvm::FoldingSetNodeID LeftID, RightID;
53  Left->Profile(LeftID);
54  Right->Profile(RightID);
55  return LeftID == RightID;
56 }
57 
58 static bool areEquivalentExpr(const Expr *Left, const Expr *Right) {
59  if (!Left || !Right)
60  return !Left && !Right;
61 
62  Left = Left->IgnoreParens();
63  Right = Right->IgnoreParens();
64 
65  // Compare classes.
66  if (Left->getStmtClass() != Right->getStmtClass())
67  return false;
68 
69  // Compare children.
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()) {
73  if (!areEquivalentExpr(dyn_cast<Expr>(*LeftIter),
74  dyn_cast<Expr>(*RightIter)))
75  return false;
76  ++LeftIter;
77  ++RightIter;
78  }
79  if (LeftIter != Left->child_end() || RightIter != Right->child_end())
80  return false;
81 
82  // Perform extra checks.
83  switch (Left->getStmtClass()) {
84  default:
85  return false;
86 
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() &&
94  LeftLit == RightLit;
95  }
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())
108  return false;
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:
125  return true;
126  case Stmt::UnaryOperatorClass:
127  if (cast<UnaryOperator>(Left)->isIncrementDecrementOp())
128  return false;
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();
134  }
135 }
136 
137 // For a given expression 'x', returns whether the ranges covered by the
138 // relational operators are equivalent (i.e. x <= 4 is equivalent to x < 5).
139 static bool areEquivalentRanges(BinaryOperatorKind OpcodeLHS,
140  const APSInt &ValueLHS,
141  BinaryOperatorKind OpcodeRHS,
142  const APSInt &ValueRHS) {
143  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
144  "Values must be ordered");
145  // Handle the case where constants are the same: x <= 4 <==> x <= 4.
146  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0)
147  return OpcodeLHS == OpcodeRHS;
148 
149  // Handle the case where constants are off by one: x <= 4 <==> x < 5.
150  APSInt ValueLHS_plus1;
151  return ((OpcodeLHS == BO_LE && OpcodeRHS == BO_LT) ||
152  (OpcodeLHS == BO_GT && OpcodeRHS == BO_GE)) &&
153  incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
154  APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0;
155 }
156 
157 // For a given expression 'x', returns whether the ranges covered by the
158 // relational operators are fully disjoint (i.e. x < 4 and x > 7).
159 static bool areExclusiveRanges(BinaryOperatorKind OpcodeLHS,
160  const APSInt &ValueLHS,
161  BinaryOperatorKind OpcodeRHS,
162  const APSInt &ValueRHS) {
163  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
164  "Values must be ordered");
165 
166  // Handle cases where the constants are the same.
167  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
168  switch (OpcodeLHS) {
169  case BO_EQ:
170  return OpcodeRHS == BO_NE || OpcodeRHS == BO_GT || OpcodeRHS == BO_LT;
171  case BO_NE:
172  return OpcodeRHS == BO_EQ;
173  case BO_LE:
174  return OpcodeRHS == BO_GT;
175  case BO_GE:
176  return OpcodeRHS == BO_LT;
177  case BO_LT:
178  return OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
179  case BO_GT:
180  return OpcodeRHS == BO_EQ || OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
181  default:
182  return false;
183  }
184  }
185 
186  // Handle cases where the constants are different.
187  if ((OpcodeLHS == BO_EQ || OpcodeLHS == BO_LT || OpcodeLHS == BO_LE) &&
188  (OpcodeRHS == BO_EQ || OpcodeRHS == BO_GT || OpcodeRHS == BO_GE))
189  return true;
190 
191  // Handle the case where constants are off by one: x > 5 && x < 6.
192  APSInt ValueLHS_plus1;
193  if (OpcodeLHS == BO_GT && OpcodeRHS == BO_LT &&
194  incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
195  APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
196  return true;
197 
198  return false;
199 }
200 
201 // Returns whether the ranges covered by the union of both relational
202 // expressions cover the whole domain (i.e. x < 10 and x > 0).
203 static bool rangesFullyCoverDomain(BinaryOperatorKind OpcodeLHS,
204  const APSInt &ValueLHS,
205  BinaryOperatorKind OpcodeRHS,
206  const APSInt &ValueRHS) {
207  assert(APSInt::compareValues(ValueLHS, ValueRHS) <= 0 &&
208  "Values must be ordered");
209 
210  // Handle cases where the constants are the same: x < 5 || x >= 5.
211  if (APSInt::compareValues(ValueLHS, ValueRHS) == 0) {
212  switch (OpcodeLHS) {
213  case BO_EQ:
214  return OpcodeRHS == BO_NE;
215  case BO_NE:
216  return OpcodeRHS == BO_EQ;
217  case BO_LE:
218  return OpcodeRHS == BO_GT || OpcodeRHS == BO_GE;
219  case BO_LT:
220  return OpcodeRHS == BO_GE;
221  case BO_GE:
222  return OpcodeRHS == BO_LT || OpcodeRHS == BO_LE;
223  case BO_GT:
224  return OpcodeRHS == BO_LE;
225  default:
226  return false;
227  }
228  }
229 
230  // Handle the case where constants are off by one: x <= 4 || x >= 5.
231  APSInt ValueLHS_plus1;
232  if (OpcodeLHS == BO_LE && OpcodeRHS == BO_GE &&
233  incrementWithoutOverflow(ValueLHS, ValueLHS_plus1) &&
234  APSInt::compareValues(ValueLHS_plus1, ValueRHS) == 0)
235  return true;
236 
237  // Handle cases where the constants are different: x > 4 || x <= 7.
238  if ((OpcodeLHS == BO_GT || OpcodeLHS == BO_GE) &&
239  (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE))
240  return true;
241 
242  // Handle cases where constants are different but both ops are !=, like:
243  // x != 5 || x != 10
244  if (OpcodeLHS == BO_NE && OpcodeRHS == BO_NE)
245  return true;
246 
247  return false;
248 }
249 
250 static bool rangeSubsumesRange(BinaryOperatorKind OpcodeLHS,
251  const APSInt &ValueLHS,
252  BinaryOperatorKind OpcodeRHS,
253  const APSInt &ValueRHS) {
254  int Comparison = APSInt::compareValues(ValueLHS, ValueRHS);
255  switch (OpcodeLHS) {
256  case BO_EQ:
257  return OpcodeRHS == BO_EQ && Comparison == 0;
258  case BO_NE:
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);
265 
266  case BO_LT:
267  return ((OpcodeRHS == BO_LT && Comparison >= 0) ||
268  (OpcodeRHS == BO_LE && Comparison > 0) ||
269  (OpcodeRHS == BO_EQ && Comparison > 0));
270  case BO_GT:
271  return ((OpcodeRHS == BO_GT && Comparison <= 0) ||
272  (OpcodeRHS == BO_GE && Comparison < 0) ||
273  (OpcodeRHS == BO_EQ && Comparison < 0));
274  case BO_LE:
275  return (OpcodeRHS == BO_LT || OpcodeRHS == BO_LE || OpcodeRHS == BO_EQ) &&
276  Comparison >= 0;
277  case BO_GE:
278  return (OpcodeRHS == BO_GT || OpcodeRHS == BO_GE || OpcodeRHS == BO_EQ) &&
279  Comparison <= 0;
280  default:
281  return false;
282  }
283 }
284 
285 static void transformSubToCanonicalAddExpr(BinaryOperatorKind &Opcode,
286  APSInt &Value) {
287  if (Opcode == BO_Sub) {
288  Opcode = BO_Add;
289  Value = -Value;
290  }
291 }
292 
293 AST_MATCHER(Expr, isIntegerConstantExpr) {
294  if (Node.isInstantiationDependent())
295  return false;
296  return Node.isIntegerConstantExpr(Finder->getASTContext());
297 }
298 
299 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
300  return areEquivalentExpr(Node.getLHS(), Node.getRHS());
301 }
302 
303 AST_MATCHER(ConditionalOperator, expressionsAreEquivalent) {
304  return areEquivalentExpr(Node.getTrueExpr(), Node.getFalseExpr());
305 }
306 
307 AST_MATCHER(CallExpr, parametersAreEquivalent) {
308  return Node.getNumArgs() == 2 &&
309  areEquivalentExpr(Node.getArg(0), Node.getArg(1));
310 }
311 
312 AST_MATCHER(BinaryOperator, binaryOperatorIsInMacro) {
313  return Node.getOperatorLoc().isMacroID();
314 }
315 
316 AST_MATCHER(ConditionalOperator, conditionalOperatorIsInMacro) {
317  return Node.getQuestionLoc().isMacroID() || Node.getColonLoc().isMacroID();
318 }
319 
320 AST_MATCHER(Expr, isMacro) { return Node.getExprLoc().isMacroID(); }
321 
322 AST_MATCHER_P(Expr, expandedByMacro, llvm::StringSet<>, Names) {
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))
329  return true;
330  Loc = SM.getImmediateMacroCallerLoc(Loc);
331  }
332  return false;
333 }
334 
335 // Returns a matcher for integer constant expressions.
336 static ast_matchers::internal::Matcher<Expr>
338  std::string CstId = (Id + "-const").str();
339  return expr(isIntegerConstantExpr()).bind(CstId);
340 }
341 
342 // Retrieves the integer expression matched by 'matchIntegerConstantExpr' with
343 // name 'Id' and stores it into 'ConstExpr', the value of the expression is
344 // stored into `Value`.
345 static bool retrieveIntegerConstantExpr(const MatchFinder::MatchResult &Result,
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);
351 }
352 
353 // Overloaded `retrieveIntegerConstantExpr` for compatibility.
354 static bool retrieveIntegerConstantExpr(const MatchFinder::MatchResult &Result,
355  StringRef Id, APSInt &Value) {
356  const Expr *ConstExpr = nullptr;
357  return retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr);
358 }
359 
360 // Returns a matcher for symbolic expressions (matches every expression except
361 // ingeter constant expressions).
362 static ast_matchers::internal::Matcher<Expr> matchSymbolicExpr(StringRef Id) {
363  std::string SymId = (Id + "-sym").str();
364  return ignoringParenImpCasts(
365  expr(unless(isIntegerConstantExpr())).bind(SymId));
366 }
367 
368 // Retrieves the expression matched by 'matchSymbolicExpr' with name 'Id' and
369 // stores it into 'SymExpr'.
370 static bool retrieveSymbolicExpr(const MatchFinder::MatchResult &Result,
371  StringRef Id, const Expr *&SymExpr) {
372  std::string SymId = (Id + "-sym").str();
373  if (const auto *Node = Result.Nodes.getNodeAs<Expr>(SymId)) {
374  SymExpr = Node;
375  return true;
376  }
377  return false;
378 }
379 
380 // Match a binary operator between a symbolic expression and an integer constant
381 // expression.
382 static ast_matchers::internal::Matcher<Expr>
384  const auto BinOpCstExpr =
385  expr(
386  anyOf(binaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("|"),
387  hasOperatorName("&")),
388  hasEitherOperand(matchSymbolicExpr(Id)),
389  hasEitherOperand(matchIntegerConstantExpr(Id))),
390  binaryOperator(hasOperatorName("-"),
391  hasLHS(matchSymbolicExpr(Id)),
392  hasRHS(matchIntegerConstantExpr(Id)))))
393  .bind(Id);
394  return ignoringParenImpCasts(BinOpCstExpr);
395 }
396 
397 // Retrieves sub-expressions matched by 'matchBinOpIntegerConstantExpr' with
398 // name 'Id'.
399 static bool
400 retrieveBinOpIntegerConstantExpr(const MatchFinder::MatchResult &Result,
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();
405  return retrieveSymbolicExpr(Result, Id, Symbol) &&
406  retrieveIntegerConstantExpr(Result, Id, Value);
407  }
408  return false;
409 }
410 
411 // Matches relational expressions: 'Expr <op> k' (i.e. x < 2, x != 3, 12 <= x).
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();
418 
419  const auto RelationalExpr = ignoringParenImpCasts(binaryOperator(
420  isComparisonOperator(), expr().bind(Id),
421  anyOf(allOf(hasLHS(matchSymbolicExpr(Id)),
422  hasRHS(matchIntegerConstantExpr(Id))),
423  allOf(hasLHS(matchIntegerConstantExpr(Id)),
424  hasRHS(matchSymbolicExpr(Id)), expr().bind(SwapId)))));
425 
426  // A cast can be matched as a comparator to zero. (i.e. if (x) is equivalent
427  // to if (x != 0)).
428  const auto CastExpr =
429  implicitCastExpr(hasCastKind(CK_IntegralToBoolean),
430  hasSourceExpression(matchSymbolicExpr(Id)))
431  .bind(CastId);
432 
433  const auto NegateRelationalExpr =
434  unaryOperator(hasOperatorName("!"),
435  hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))
436  .bind(NegateId);
437 
438  // Do not bind to double negation.
439  const auto NegateNegateRelationalExpr =
440  unaryOperator(hasOperatorName("!"),
441  hasUnaryOperand(unaryOperator(
442  hasOperatorName("!"),
443  hasUnaryOperand(anyOf(CastExpr, RelationalExpr)))));
444 
445  const auto OverloadedOperatorExpr =
446  cxxOperatorCallExpr(
447  anyOf(hasOverloadedOperatorName("=="),
448  hasOverloadedOperatorName("!="), hasOverloadedOperatorName("<"),
449  hasOverloadedOperatorName("<="), hasOverloadedOperatorName(">"),
450  hasOverloadedOperatorName(">=")),
451  // Filter noisy false positives.
452  unless(isMacro()), unless(isInTemplateInstantiation()))
453  .bind(OverloadId);
454 
455  return anyOf(RelationalExpr, CastExpr, NegateRelationalExpr,
456  NegateNegateRelationalExpr, OverloadedOperatorExpr);
457 }
458 
459 // Checks whether a function param is non constant reference type, and may
460 // be modified in the function.
461 static bool isNonConstReferenceType(QualType ParamType) {
462  return ParamType->isReferenceType() &&
463  !ParamType.getNonReferenceType().isConstQualified();
464 }
465 
466 // Checks whether the arguments of an overloaded operator can be modified in the
467 // function.
468 // For operators that take an instance and a constant as arguments, only the
469 // first argument (the instance) needs to be checked, since the constant itself
470 // is a temporary expression. Whether the second parameter is checked is
471 // controlled by the parameter `ParamsToCheckCount`.
472 static bool
473 canOverloadedOperatorArgsBeModified(const FunctionDecl *OperatorDecl,
474  bool checkSecondParam) {
475  unsigned ParamCount = OperatorDecl->getNumParams();
476 
477  // Overloaded operators declared inside a class have only one param.
478  // These functions must be declared const in order to not be able to modify
479  // the instance of the class they are called through.
480  if (ParamCount == 1 &&
481  !OperatorDecl->getType()->getAs<FunctionType>()->isConst())
482  return true;
483 
484  if (isNonConstReferenceType(OperatorDecl->getParamDecl(0)->getType()))
485  return true;
486 
487  return checkSecondParam && ParamCount == 2 &&
488  isNonConstReferenceType(OperatorDecl->getParamDecl(1)->getType());
489 }
490 
491 // Retrieves sub-expressions matched by 'matchRelationalIntegerConstantExpr'
492 // with name 'Id'.
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();
501 
502  if (const auto *Bin = Result.Nodes.getNodeAs<BinaryOperator>(Id)) {
503  // Operand received with explicit comparator.
504  Opcode = Bin->getOpcode();
505  OperandExpr = Bin;
506 
507  if (!retrieveIntegerConstantExpr(Result, Id, Value, ConstExpr))
508  return false;
509  } else if (const auto *Cast = Result.Nodes.getNodeAs<CastExpr>(CastId)) {
510  // Operand received with implicit comparator (cast).
511  Opcode = BO_NE;
512  OperandExpr = Cast;
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)
518  return false;
519 
520  if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false))
521  return false;
522 
523  if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, false))
524  return false;
525 
526  if (!OverloadedOperatorExpr->getArg(1)->isIntegerConstantExpr(
527  Value, *Result.Context))
528  return false;
529 
530  Symbol = OverloadedOperatorExpr->getArg(0);
531  OperandExpr = OverloadedOperatorExpr;
532  Opcode = BinaryOperator::getOverloadedOpcode(OverloadedOperatorExpr->getOperator());
533 
534  return BinaryOperator::isComparisonOp(Opcode);
535  } else {
536  return false;
537  }
538 
539  if (!retrieveSymbolicExpr(Result, Id, Symbol))
540  return false;
541 
542  if (Result.Nodes.getNodeAs<Expr>(SwapId))
543  Opcode = BinaryOperator::reverseComparisonOp(Opcode);
544  if (Result.Nodes.getNodeAs<Expr>(NegateId))
545  Opcode = BinaryOperator::negateComparisonOp(Opcode);
546  return true;
547 }
548 
549 // Checks for expressions like (X == 4) && (Y != 9)
550 static bool areSidesBinaryConstExpressions(const BinaryOperator *&BinOp, const ASTContext *AstCtx) {
551  const auto *LhsBinOp = dyn_cast<BinaryOperator>(BinOp->getLHS());
552  const auto *RhsBinOp = dyn_cast<BinaryOperator>(BinOp->getRHS());
553 
554  if (!LhsBinOp || !RhsBinOp)
555  return false;
556 
557  if ((LhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
558  LhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)) &&
559  (RhsBinOp->getLHS()->isIntegerConstantExpr(*AstCtx) ||
560  RhsBinOp->getRHS()->isIntegerConstantExpr(*AstCtx)))
561  return true;
562  return false;
563 }
564 
565 // Retrieves integer constant subexpressions from binary operator expressions
566 // that have two equivalent sides.
567 // E.g.: from (X == 5) && (X == 5) retrieves 5 and 5.
568 static bool retrieveConstExprFromBothSides(const BinaryOperator *&BinOp,
569  BinaryOperatorKind &MainOpcode,
570  BinaryOperatorKind &SideOpcode,
571  const Expr *&LhsConst,
572  const Expr *&RhsConst,
573  const ASTContext *AstCtx) {
574  assert(areSidesBinaryConstExpressions(BinOp, AstCtx) &&
575  "Both sides of binary operator must be constant expressions!");
576 
577  MainOpcode = BinOp->getOpcode();
578 
579  const auto *BinOpLhs = cast<BinaryOperator>(BinOp->getLHS());
580  const auto *BinOpRhs = cast<BinaryOperator>(BinOp->getRHS());
581 
582  LhsConst = BinOpLhs->getLHS()->isIntegerConstantExpr(*AstCtx)
583  ? BinOpLhs->getLHS()
584  : BinOpLhs->getRHS();
585  RhsConst = BinOpRhs->getLHS()->isIntegerConstantExpr(*AstCtx)
586  ? BinOpRhs->getLHS()
587  : BinOpRhs->getRHS();
588 
589  if (!LhsConst || !RhsConst)
590  return false;
591 
592  assert(BinOpLhs->getOpcode() == BinOpRhs->getOpcode() &&
593  "Sides of the binary operator must be equivalent expressions!");
594 
595  SideOpcode = BinOpLhs->getOpcode();
596 
597  return true;
598 }
599 
600 static bool areExprsFromDifferentMacros(const Expr *LhsExpr,
601  const Expr *RhsExpr,
602  const ASTContext *AstCtx) {
603  if (!LhsExpr || !RhsExpr)
604  return false;
605 
606  SourceLocation LhsLoc = LhsExpr->getExprLoc();
607  SourceLocation RhsLoc = RhsExpr->getExprLoc();
608 
609  if (!LhsLoc.isMacroID() || !RhsLoc.isMacroID())
610  return false;
611 
612  const SourceManager &SM = AstCtx->getSourceManager();
613  const LangOptions &LO = AstCtx->getLangOpts();
614 
615  return !(Lexer::getImmediateMacroName(LhsLoc, SM, LO) ==
616  Lexer::getImmediateMacroName(RhsLoc, SM, LO));
617 }
618 
619 static bool areExprsMacroAndNonMacro(const Expr *&LhsExpr,
620  const Expr *&RhsExpr) {
621  if (!LhsExpr || !RhsExpr)
622  return false;
623 
624  SourceLocation LhsLoc = LhsExpr->getExprLoc();
625  SourceLocation RhsLoc = RhsExpr->getExprLoc();
626 
627  return LhsLoc.isMacroID() != RhsLoc.isMacroID();
628 }
629 
630 void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) {
631  const auto AnyLiteralExpr = ignoringParenImpCasts(
632  anyOf(cxxBoolLiteral(), characterLiteral(), integerLiteral()));
633 
634  const auto BannedIntegerLiteral =
635  integerLiteral(expandedByMacro(KnownBannedMacroNames));
636 
637  // Binary with equivalent operands, like (X != 2 && X != 2).
638  Finder->addMatcher(
639  binaryOperator(anyOf(hasOperatorName("-"), hasOperatorName("/"),
640  hasOperatorName("%"), hasOperatorName("|"),
641  hasOperatorName("&"), hasOperatorName("^"),
642  matchers::isComparisonOperator(),
643  hasOperatorName("&&"), hasOperatorName("||"),
644  hasOperatorName("=")),
645  operandsAreEquivalent(),
646  // Filter noisy false positives.
647  unless(isInTemplateInstantiation()),
648  unless(binaryOperatorIsInMacro()),
649  unless(hasType(realFloatingPointType())),
650  unless(hasEitherOperand(hasType(realFloatingPointType()))),
651  unless(hasLHS(AnyLiteralExpr)),
652  unless(hasDescendant(BannedIntegerLiteral)))
653  .bind("binary"),
654  this);
655 
656  // Conditional (trenary) operator with equivalent operands, like (Y ? X : X).
657  Finder->addMatcher(conditionalOperator(expressionsAreEquivalent(),
658  // Filter noisy false positives.
659  unless(conditionalOperatorIsInMacro()),
660  unless(isInTemplateInstantiation()))
661  .bind("cond"),
662  this);
663 
664  // Overloaded operators with equivalent operands.
665  Finder->addMatcher(
666  cxxOperatorCallExpr(
667  anyOf(
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(),
677  // Filter noisy false positives.
678  unless(isMacro()), unless(isInTemplateInstantiation()))
679  .bind("call"),
680  this);
681 
682  // Match expressions like: !(1 | 2 | 3)
683  Finder->addMatcher(
684  implicitCastExpr(
685  hasImplicitDestinationType(isInteger()),
686  has(unaryOperator(
687  hasOperatorName("!"),
688  hasUnaryOperand(ignoringParenImpCasts(binaryOperator(
689  anyOf(hasOperatorName("|"), hasOperatorName("&")),
690  hasLHS(anyOf(binaryOperator(anyOf(hasOperatorName("|"),
691  hasOperatorName("&"))),
692  integerLiteral())),
693  hasRHS(integerLiteral())))))
694  .bind("logical-bitwise-confusion"))),
695  this);
696 
697  // Match expressions like: (X << 8) & 0xFF
698  Finder->addMatcher(
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"),
707  this);
708 
709  // Match common expressions and apply more checks to find redundant
710  // sub-expressions.
711  // a) Expr <op> K1 == K2
712  // b) Expr <op> K1 == Expr
713  // c) Expr <op> K1 == Expr <op> K2
714  // see: 'checkArithmeticExpr' and 'checkBitwiseExpr'
715  const auto BinOpCstLeft = matchBinOpIntegerConstantExpr("lhs");
716  const auto BinOpCstRight = matchBinOpIntegerConstantExpr("rhs");
717  const auto CstRight = matchIntegerConstantExpr("rhs");
718  const auto SymRight = matchSymbolicExpr("rhs");
719 
720  // Match expressions like: x <op> 0xFF == 0xF00.
721  Finder->addMatcher(binaryOperator(isComparisonOperator(),
722  hasEitherOperand(BinOpCstLeft),
723  hasEitherOperand(CstRight))
724  .bind("binop-const-compare-to-const"),
725  this);
726 
727  // Match expressions like: x <op> 0xFF == x.
728  Finder->addMatcher(
729  binaryOperator(isComparisonOperator(),
730  anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)),
731  allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft))))
732  .bind("binop-const-compare-to-sym"),
733  this);
734 
735  // Match expressions like: x <op> 10 == x <op> 12.
736  Finder->addMatcher(binaryOperator(isComparisonOperator(),
737  hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight),
738  // Already reported as redundant.
739  unless(operandsAreEquivalent()))
740  .bind("binop-const-compare-to-binop-const"),
741  this);
742 
743  // Match relational expressions combined with logical operators and find
744  // redundant sub-expressions.
745  // see: 'checkRelationalExpr'
746 
747  // Match expressions like: x < 2 && x > 2.
748  const auto ComparisonLeft = matchRelationalIntegerConstantExpr("lhs");
749  const auto ComparisonRight = matchRelationalIntegerConstantExpr("rhs");
750  Finder->addMatcher(
751  binaryOperator(anyOf(hasOperatorName("||"), hasOperatorName("&&")),
752  hasLHS(ComparisonLeft), hasRHS(ComparisonRight),
753  // Already reported as redundant.
754  unless(operandsAreEquivalent()))
755  .bind("comparisons-of-symbol-and-const"),
756  this);
757 }
758 
759 void RedundantExpressionCheck::checkArithmeticExpr(
760  const MatchFinder::MatchResult &Result) {
761  APSInt LhsValue, RhsValue;
762  const Expr *LhsSymbol = nullptr, *RhsSymbol = nullptr;
763  BinaryOperatorKind LhsOpcode, RhsOpcode;
764 
765  if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
766  "binop-const-compare-to-sym")) {
767  BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
768  if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
769  LhsValue) ||
770  !retrieveSymbolicExpr(Result, "rhs", RhsSymbol) ||
771  !areEquivalentExpr(LhsSymbol, RhsSymbol))
772  return;
773 
774  // Check expressions: x + k == x or x - k == x.
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");
784  }
785  } else if (const auto *ComparisonOperator =
786  Result.Nodes.getNodeAs<BinaryOperator>(
787  "binop-const-compare-to-binop-const")) {
788  BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
789 
790  if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
791  LhsValue) ||
792  !retrieveBinOpIntegerConstantExpr(Result, "rhs", RhsOpcode, RhsSymbol,
793  RhsValue) ||
794  !areEquivalentExpr(LhsSymbol, RhsSymbol))
795  return;
796 
797  transformSubToCanonicalAddExpr(LhsOpcode, LhsValue);
798  transformSubToCanonicalAddExpr(RhsOpcode, RhsValue);
799 
800  // Check expressions: x + 1 == x + 2 or x + 1 != x + 2.
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) ||
808  (Opcode == BO_NE &&
809  APSInt::compareValues(LhsValue, RhsValue) == 0)) {
810  diag(ComparisonOperator->getOperatorLoc(),
811  "logical expression is always false");
812  }
813  }
814  }
815 }
816 
817 static bool exprEvaluatesToZero(BinaryOperatorKind Opcode, APSInt Value) {
818  return (Opcode == BO_And || Opcode == BO_AndAssign) && Value == 0;
819 }
820 
821 static bool exprEvaluatesToBitwiseNegatedZero(BinaryOperatorKind Opcode,
822  APSInt Value) {
823  return (Opcode == BO_Or || Opcode == BO_OrAssign) && ~Value == 0;
824 }
825 
826 static bool exprEvaluatesToSymbolic(BinaryOperatorKind Opcode, APSInt Value) {
827  return ((Opcode == BO_Or || Opcode == BO_OrAssign) && Value == 0) ||
828  ((Opcode == BO_And || Opcode == BO_AndAssign) && ~Value == 0);
829 }
830 
831 
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();
837 
838  APSInt LhsValue, RhsValue;
839  const Expr *LhsSymbol = nullptr;
840  BinaryOperatorKind LhsOpcode;
841  if (!retrieveBinOpIntegerConstantExpr(Result, "lhs", LhsOpcode, LhsSymbol,
842  LhsValue) ||
843  !retrieveIntegerConstantExpr(Result, "rhs", RhsValue))
844  return;
845 
846  uint64_t LhsConstant = LhsValue.getZExtValue();
847  uint64_t RhsConstant = RhsValue.getZExtValue();
848  SourceLocation Loc = ComparisonOperator->getOperatorLoc();
849 
850  // Check expression: x & k1 == k2 (i.e. x & 0xFF == 0xF00)
851  if (LhsOpcode == BO_And && (LhsConstant & RhsConstant) != RhsConstant) {
852  if (Opcode == BO_EQ)
853  diag(Loc, "logical expression is always false");
854  else if (Opcode == BO_NE)
855  diag(Loc, "logical expression is always true");
856  }
857 
858  // Check expression: x | k1 == k2 (i.e. x | 0xFF == 0xF00)
859  if (LhsOpcode == BO_Or && (LhsConstant | RhsConstant) != RhsConstant) {
860  if (Opcode == BO_EQ)
861  diag(Loc, "logical expression is always false");
862  else if (Opcode == BO_NE)
863  diag(Loc, "logical expression is always true");
864  }
865  } else if (const auto *IneffectiveOperator =
866  Result.Nodes.getNodeAs<BinaryOperator>(
867  "ineffective-bitwise")) {
868  APSInt Value;
869  const Expr *Sym = nullptr, *ConstExpr = nullptr;
870 
871  if (!retrieveSymbolicExpr(Result, "ineffective-bitwise", Sym) ||
872  !retrieveIntegerConstantExpr(Result, "ineffective-bitwise", Value,
873  ConstExpr))
874  return;
875 
876  if((Value != 0 && ~Value != 0) || Sym->getExprLoc().isMacroID())
877  return;
878 
879  SourceLocation Loc = IneffectiveOperator->getOperatorLoc();
880 
881  BinaryOperatorKind Opcode = IneffectiveOperator->getOpcode();
882  if (exprEvaluatesToZero(Opcode, Value)) {
883  diag(Loc, "expression always evaluates to 0");
884  } else if (exprEvaluatesToBitwiseNegatedZero(Opcode, Value)) {
885  SourceRange ConstExprRange(ConstExpr->getLocStart(),
886  ConstExpr->getLocEnd());
887  StringRef ConstExprText = Lexer::getSourceText(
888  CharSourceRange::getTokenRange(ConstExprRange), *Result.SourceManager,
889  Result.Context->getLangOpts());
890 
891  diag(Loc, "expression always evaluates to '%0'") << ConstExprText;
892 
893  } else if (exprEvaluatesToSymbolic(Opcode, Value)) {
894  SourceRange SymExprRange(Sym->getLocStart(), Sym->getLocEnd());
895 
896  StringRef ExprText = Lexer::getSourceText(
897  CharSourceRange::getTokenRange(SymExprRange), *Result.SourceManager,
898  Result.Context->getLangOpts());
899 
900  diag(Loc, "expression always evaluates to '%0'") << ExprText;
901  }
902  }
903 }
904 
905 void RedundantExpressionCheck::checkRelationalExpr(
906  const MatchFinder::MatchResult &Result) {
907  if (const auto *ComparisonOperator = Result.Nodes.getNodeAs<BinaryOperator>(
908  "comparisons-of-symbol-and-const")) {
909  // Matched expressions are: (x <op> k1) <REL> (x <op> k2).
910  // E.g.: (X < 2) && (X > 4)
911  BinaryOperatorKind Opcode = ComparisonOperator->getOpcode();
912 
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;
918 
920  Result, "lhs", LhsExpr, LhsOpcode, LhsSymbol, LhsValue, LhsConst) ||
922  Result, "rhs", RhsExpr, RhsOpcode, RhsSymbol, RhsValue, RhsConst) ||
923  !areEquivalentExpr(LhsSymbol, RhsSymbol))
924  return;
925 
926  // Bring expr to a canonical form: smallest constant must be on the left.
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);
932  }
933 
934  // Constants come from two different macros, or one of them is a macro.
935  if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
936  areExprsMacroAndNonMacro(LhsConst, RhsConst))
937  return;
938 
939  if ((Opcode == BO_LAnd || Opcode == BO_LOr) &&
940  areEquivalentRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
941  diag(ComparisonOperator->getOperatorLoc(),
942  "equivalent expression on both sides of logical operator");
943  return;
944  }
945 
946  if (Opcode == BO_LAnd) {
947  if (areExclusiveRanges(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
948  diag(ComparisonOperator->getOperatorLoc(),
949  "logical expression is always false");
950  } else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
951  diag(LhsExpr->getExprLoc(), "expression is redundant");
952  } else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
953  diag(RhsExpr->getExprLoc(), "expression is redundant");
954  }
955  }
956 
957  if (Opcode == BO_LOr) {
958  if (rangesFullyCoverDomain(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
959  diag(ComparisonOperator->getOperatorLoc(),
960  "logical expression is always true");
961  } else if (rangeSubsumesRange(LhsOpcode, LhsValue, RhsOpcode, RhsValue)) {
962  diag(RhsExpr->getExprLoc(), "expression is redundant");
963  } else if (rangeSubsumesRange(RhsOpcode, RhsValue, LhsOpcode, LhsValue)) {
964  diag(LhsExpr->getExprLoc(), "expression is redundant");
965  }
966  }
967  }
968 }
969 
970 void RedundantExpressionCheck::check(const MatchFinder::MatchResult &Result) {
971  if (const auto *BinOp = Result.Nodes.getNodeAs<BinaryOperator>("binary")) {
972  // If the expression's constants are macros, check whether they are
973  // intentional.
974  if (areSidesBinaryConstExpressions(BinOp, Result.Context)) {
975  const Expr *LhsConst = nullptr, *RhsConst = nullptr;
976  BinaryOperatorKind MainOpcode, SideOpcode;
977 
978  if (!retrieveConstExprFromBothSides(BinOp, MainOpcode, SideOpcode,
979  LhsConst, RhsConst, Result.Context))
980  return;
981 
982  if (areExprsFromDifferentMacros(LhsConst, RhsConst, Result.Context) ||
983  areExprsMacroAndNonMacro(LhsConst, RhsConst))
984  return;
985  }
986 
987  diag(BinOp->getOperatorLoc(), "both sides of operator are equivalent");
988  }
989 
990  if (const auto *CondOp =
991  Result.Nodes.getNodeAs<ConditionalOperator>("cond")) {
992  const Expr *TrueExpr = CondOp->getTrueExpr();
993  const Expr *FalseExpr = CondOp->getFalseExpr();
994 
995  if (areExprsFromDifferentMacros(TrueExpr, FalseExpr, Result.Context) ||
996  areExprsMacroAndNonMacro(TrueExpr, FalseExpr))
997  return;
998  diag(CondOp->getColonLoc(),
999  "'true' and 'false' expressions are equivalent");
1000  }
1001 
1002  if (const auto *Call = Result.Nodes.getNodeAs<CXXOperatorCallExpr>("call")) {
1003  const auto *OverloadedFunctionDecl = dyn_cast_or_null<FunctionDecl>(Call->getCalleeDecl());
1004  if (!OverloadedFunctionDecl)
1005  return;
1006 
1007  if (canOverloadedOperatorArgsBeModified(OverloadedFunctionDecl, true))
1008  return;
1009 
1010  diag(Call->getOperatorLoc(),
1011  "both sides of overloaded operator are equivalent");
1012  }
1013 
1014  if (const auto *NegateOperator =
1015  Result.Nodes.getNodeAs<UnaryOperator>("logical-bitwise-confusion")) {
1016  SourceLocation OperatorLoc = NegateOperator->getOperatorLoc();
1017 
1018  auto Diag =
1019  diag(OperatorLoc,
1020  "ineffective logical negation operator used; did you mean '~'?");
1021  SourceLocation LogicalNotLocation = OperatorLoc.getLocWithOffset(1);
1022 
1023  if (!LogicalNotLocation.isMacroID())
1024  Diag << FixItHint::CreateReplacement(
1025  CharSourceRange::getCharRange(OperatorLoc, LogicalNotLocation), "~");
1026  }
1027 
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;
1033 
1034  if (!ShiftingConst->isIntegerConstantExpr(ShiftingValue, *Result.Context))
1035  return;
1036 
1037  const auto *AndConst = Result.Nodes.getNodeAs<Expr>("and-const");
1038  assert(AndConst && "Expr* 'AndCont' is nullptr!");
1039  APSInt AndValue;
1040  if (!AndConst->isIntegerConstantExpr(AndValue, *Result.Context))
1041  return;
1042 
1043  // If ShiftingConst is shifted left with more bits than the position of the
1044  // leftmost 1 in the bit representation of AndValue, AndConstant is
1045  // ineffective.
1046  if (floor(log2(AndValue.getExtValue())) >= ShiftingValue)
1047  return;
1048 
1049  auto Diag = diag(BinaryAndExpr->getOperatorLoc(),
1050  "ineffective bitwise and operation.");
1051  }
1052 
1053  // Check for the following bound expressions:
1054  // - "binop-const-compare-to-sym",
1055  // - "binop-const-compare-to-binop-const",
1056  // Produced message:
1057  // -> "logical expression is always false/true"
1058  checkArithmeticExpr(Result);
1059 
1060  // Check for the following bound expression:
1061  // - "binop-const-compare-to-const",
1062  // - "ineffective-bitwise"
1063  // Produced message:
1064  // -> "logical expression is always false/true"
1065  // -> "expression always evaluates to ..."
1066  checkBitwiseExpr(Result);
1067 
1068  // Check for te following bound expression:
1069  // - "comparisons-of-symbol-and-const",
1070  // Produced messages:
1071  // -> "equivalent expression on both sides of logical operator",
1072  // -> "logical expression is always false/true"
1073  // -> "expression is redundant"
1074  checkRelationalExpr(Result);
1075 }
1076 
1077 } // namespace misc
1078 } // namespace tidy
1079 } // namespace clang
SourceLocation Loc
&#39;#&#39; 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)