1//== IdenticalExprChecker.cpp - Identical expression checker----------------==//
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///
10/// \file
11/// \brief This defines IdenticalExprChecker, a check that warns about
12/// unintended use of identical expressions.
13///
14/// It checks for use of identical expressions with comparison operators and
15/// inside conditional expressions.
16///
17//===----------------------------------------------------------------------===//
18
19#include "ClangSACheckers.h"
20#include "clang/AST/RecursiveASTVisitor.h"
21#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
22#include "clang/StaticAnalyzer/Core/Checker.h"
23#include "clang/StaticAnalyzer/Core/CheckerManager.h"
24#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
25
26using namespace clang;
27using namespace ento;
28
29static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
30                            const Stmt *Stmt2, bool IgnoreSideEffects = false);
31//===----------------------------------------------------------------------===//
32// FindIdenticalExprVisitor - Identify nodes using identical expressions.
33//===----------------------------------------------------------------------===//
34
35namespace {
36class FindIdenticalExprVisitor
37    : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
38  BugReporter &BR;
39  const CheckerBase *Checker;
40  AnalysisDeclContext *AC;
41public:
42  explicit FindIdenticalExprVisitor(BugReporter &B,
43                                    const CheckerBase *Checker,
44                                    AnalysisDeclContext *A)
45      : BR(B), Checker(Checker), AC(A) {}
46  // FindIdenticalExprVisitor only visits nodes
47  // that are binary operators, if statements or
48  // conditional operators.
49  bool VisitBinaryOperator(const BinaryOperator *B);
50  bool VisitIfStmt(const IfStmt *I);
51  bool VisitConditionalOperator(const ConditionalOperator *C);
52
53private:
54  void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise,
55                           ArrayRef<SourceRange> Sr);
56  void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise);
57  void checkComparisonOp(const BinaryOperator *B);
58};
59} // end anonymous namespace
60
61void FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B,
62                                                   bool CheckBitwise,
63                                                   ArrayRef<SourceRange> Sr) {
64  StringRef Message;
65  if (CheckBitwise)
66    Message = "identical expressions on both sides of bitwise operator";
67  else
68    Message = "identical expressions on both sides of logical operator";
69
70  PathDiagnosticLocation ELoc =
71      PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
72  BR.EmitBasicReport(AC->getDecl(), Checker,
73                     "Use of identical expressions",
74                     categories::LogicError,
75                     Message, ELoc, Sr);
76}
77
78void FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
79                                                       bool CheckBitwise) {
80  SourceRange Sr[2];
81
82  const Expr *LHS = B->getLHS();
83  const Expr *RHS = B->getRHS();
84
85  // Split operators as long as we still have operators to split on. We will
86  // get called for every binary operator in an expression so there is no need
87  // to check every one against each other here, just the right most one with
88  // the others.
89  while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) {
90    if (B->getOpcode() != B2->getOpcode())
91      break;
92    if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) {
93      Sr[0] = RHS->getSourceRange();
94      Sr[1] = B2->getRHS()->getSourceRange();
95      reportIdenticalExpr(B, CheckBitwise, Sr);
96    }
97    LHS = B2->getLHS();
98  }
99
100  if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) {
101    Sr[0] = RHS->getSourceRange();
102    Sr[1] = LHS->getSourceRange();
103    reportIdenticalExpr(B, CheckBitwise, Sr);
104  }
105}
106
107bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
108  const Stmt *Stmt1 = I->getThen();
109  const Stmt *Stmt2 = I->getElse();
110
111  // Check for identical inner condition:
112  //
113  // if (x<10) {
114  //   if (x<10) {
115  //   ..
116  if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(Stmt1)) {
117    if (!CS->body_empty()) {
118      const IfStmt *InnerIf = dyn_cast<IfStmt>(*CS->body_begin());
119      if (InnerIf && isIdenticalStmt(AC->getASTContext(), I->getCond(), InnerIf->getCond(), /*ignoreSideEffects=*/ false)) {
120        PathDiagnosticLocation ELoc(InnerIf->getCond(), BR.getSourceManager(), AC);
121        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
122          categories::LogicError,
123          "conditions of the inner and outer statements are identical",
124          ELoc);
125      }
126    }
127  }
128
129  // Check for identical conditions:
130  //
131  // if (b) {
132  //   foo1();
133  // } else if (b) {
134  //   foo2();
135  // }
136  if (Stmt1 && Stmt2) {
137    const Expr *Cond1 = I->getCond();
138    const Stmt *Else = Stmt2;
139    while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
140      const Expr *Cond2 = I2->getCond();
141      if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
142        SourceRange Sr = Cond1->getSourceRange();
143        PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
144        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
145                           categories::LogicError,
146                           "expression is identical to previous condition",
147                           ELoc, Sr);
148      }
149      Else = I2->getElse();
150    }
151  }
152
153  if (!Stmt1 || !Stmt2)
154    return true;
155
156  // Special handling for code like:
157  //
158  // if (b) {
159  //   i = 1;
160  // } else
161  //   i = 1;
162  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) {
163    if (CompStmt->size() == 1)
164      Stmt1 = CompStmt->body_back();
165  }
166  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) {
167    if (CompStmt->size() == 1)
168      Stmt2 = CompStmt->body_back();
169  }
170
171  if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) {
172      PathDiagnosticLocation ELoc =
173          PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC);
174      BR.EmitBasicReport(AC->getDecl(), Checker,
175                         "Identical branches",
176                         categories::LogicError,
177                         "true and false branches are identical", ELoc);
178  }
179  return true;
180}
181
182bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
183  BinaryOperator::Opcode Op = B->getOpcode();
184
185  if (BinaryOperator::isBitwiseOp(Op))
186    checkBitwiseOrLogicalOp(B, true);
187
188  if (BinaryOperator::isLogicalOp(Op))
189    checkBitwiseOrLogicalOp(B, false);
190
191  if (BinaryOperator::isComparisonOp(Op))
192    checkComparisonOp(B);
193
194  // We want to visit ALL nodes (subexpressions of binary comparison
195  // expressions too) that contains comparison operators.
196  // True is always returned to traverse ALL nodes.
197  return true;
198}
199
200void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
201  BinaryOperator::Opcode Op = B->getOpcode();
202
203  //
204  // Special case for floating-point representation.
205  //
206  // If expressions on both sides of comparison operator are of type float,
207  // then for some comparison operators no warning shall be
208  // reported even if the expressions are identical from a symbolic point of
209  // view. Comparison between expressions, declared variables and literals
210  // are treated differently.
211  //
212  // != and == between float literals that have the same value should NOT warn.
213  // < > between float literals that have the same value SHOULD warn.
214  //
215  // != and == between the same float declaration should NOT warn.
216  // < > between the same float declaration SHOULD warn.
217  //
218  // != and == between eq. expressions that evaluates into float
219  //           should NOT warn.
220  // < >       between eq. expressions that evaluates into float
221  //           should NOT warn.
222  //
223  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
224  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();
225
226  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
227  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
228  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
229  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
230  if ((DeclRef1) && (DeclRef2)) {
231    if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
232        (DeclRef2->getType()->hasFloatingRepresentation())) {
233      if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
234        if ((Op == BO_EQ) || (Op == BO_NE)) {
235          return;
236        }
237      }
238    }
239  } else if ((FloatLit1) && (FloatLit2)) {
240    if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
241      if ((Op == BO_EQ) || (Op == BO_NE)) {
242        return;
243      }
244    }
245  } else if (LHS->getType()->hasFloatingRepresentation()) {
246    // If any side of comparison operator still has floating-point
247    // representation, then it's an expression. Don't warn.
248    // Here only LHS is checked since RHS will be implicit casted to float.
249    return;
250  } else {
251    // No special case with floating-point representation, report as usual.
252  }
253
254  if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) {
255    PathDiagnosticLocation ELoc =
256        PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
257    StringRef Message;
258    if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
259      Message = "comparison of identical expressions always evaluates to true";
260    else
261      Message = "comparison of identical expressions always evaluates to false";
262    BR.EmitBasicReport(AC->getDecl(), Checker,
263                       "Compare of identical expressions",
264                       categories::LogicError, Message, ELoc);
265  }
266}
267
268bool FindIdenticalExprVisitor::VisitConditionalOperator(
269    const ConditionalOperator *C) {
270
271  // Check if expressions in conditional expression are identical
272  // from a symbolic point of view.
273
274  if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(),
275                      C->getFalseExpr(), true)) {
276    PathDiagnosticLocation ELoc =
277        PathDiagnosticLocation::createConditionalColonLoc(
278            C, BR.getSourceManager());
279
280    SourceRange Sr[2];
281    Sr[0] = C->getTrueExpr()->getSourceRange();
282    Sr[1] = C->getFalseExpr()->getSourceRange();
283    BR.EmitBasicReport(
284        AC->getDecl(), Checker,
285        "Identical expressions in conditional expression",
286        categories::LogicError,
287        "identical expressions on both sides of ':' in conditional expression",
288        ELoc, Sr);
289  }
290  // We want to visit ALL nodes (expressions in conditional
291  // expressions too) that contains conditional operators,
292  // thus always return true to traverse ALL nodes.
293  return true;
294}
295
296/// \brief Determines whether two statement trees are identical regarding
297/// operators and symbols.
298///
299/// Exceptions: expressions containing macros or functions with possible side
300/// effects are never considered identical.
301/// Limitations: (t + u) and (u + t) are not considered identical.
302/// t*(u + t) and t*u + t*t are not considered identical.
303///
304static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
305                            const Stmt *Stmt2, bool IgnoreSideEffects) {
306
307  if (!Stmt1 || !Stmt2) {
308    return !Stmt1 && !Stmt2;
309  }
310
311  // If Stmt1 & Stmt2 are of different class then they are not
312  // identical statements.
313  if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
314    return false;
315
316  const Expr *Expr1 = dyn_cast<Expr>(Stmt1);
317  const Expr *Expr2 = dyn_cast<Expr>(Stmt2);
318
319  if (Expr1 && Expr2) {
320    // If Stmt1 has side effects then don't warn even if expressions
321    // are identical.
322    if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx))
323      return false;
324    // If either expression comes from a macro then don't warn even if
325    // the expressions are identical.
326    if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
327      return false;
328
329    // If all children of two expressions are identical, return true.
330    Expr::const_child_iterator I1 = Expr1->child_begin();
331    Expr::const_child_iterator I2 = Expr2->child_begin();
332    while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
333      if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
334        return false;
335      ++I1;
336      ++I2;
337    }
338    // If there are different number of children in the statements, return
339    // false.
340    if (I1 != Expr1->child_end())
341      return false;
342    if (I2 != Expr2->child_end())
343      return false;
344  }
345
346  switch (Stmt1->getStmtClass()) {
347  default:
348    return false;
349  case Stmt::CallExprClass:
350  case Stmt::ArraySubscriptExprClass:
351  case Stmt::OMPArraySectionExprClass:
352  case Stmt::ImplicitCastExprClass:
353  case Stmt::ParenExprClass:
354  case Stmt::BreakStmtClass:
355  case Stmt::ContinueStmtClass:
356  case Stmt::NullStmtClass:
357    return true;
358  case Stmt::CStyleCastExprClass: {
359    const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1);
360    const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2);
361
362    return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
363  }
364  case Stmt::ReturnStmtClass: {
365    const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
366    const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
367
368    return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(),
369                           ReturnStmt2->getRetValue(), IgnoreSideEffects);
370  }
371  case Stmt::ForStmtClass: {
372    const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1);
373    const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2);
374
375    if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(),
376                         IgnoreSideEffects))
377      return false;
378    if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(),
379                         IgnoreSideEffects))
380      return false;
381    if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(),
382                         IgnoreSideEffects))
383      return false;
384    if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(),
385                         IgnoreSideEffects))
386      return false;
387    return true;
388  }
389  case Stmt::DoStmtClass: {
390    const DoStmt *DStmt1 = cast<DoStmt>(Stmt1);
391    const DoStmt *DStmt2 = cast<DoStmt>(Stmt2);
392
393    if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(),
394                         IgnoreSideEffects))
395      return false;
396    if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(),
397                         IgnoreSideEffects))
398      return false;
399    return true;
400  }
401  case Stmt::WhileStmtClass: {
402    const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1);
403    const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2);
404
405    if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(),
406                         IgnoreSideEffects))
407      return false;
408    if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(),
409                         IgnoreSideEffects))
410      return false;
411    return true;
412  }
413  case Stmt::IfStmtClass: {
414    const IfStmt *IStmt1 = cast<IfStmt>(Stmt1);
415    const IfStmt *IStmt2 = cast<IfStmt>(Stmt2);
416
417    if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(),
418                         IgnoreSideEffects))
419      return false;
420    if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(),
421                         IgnoreSideEffects))
422      return false;
423    if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(),
424                         IgnoreSideEffects))
425      return false;
426    return true;
427  }
428  case Stmt::CompoundStmtClass: {
429    const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1);
430    const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2);
431
432    if (CompStmt1->size() != CompStmt2->size())
433      return false;
434
435    CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin();
436    CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin();
437    while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) {
438      if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
439        return false;
440      ++I1;
441      ++I2;
442    }
443
444    return true;
445  }
446  case Stmt::CompoundAssignOperatorClass:
447  case Stmt::BinaryOperatorClass: {
448    const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1);
449    const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2);
450    return BinOp1->getOpcode() == BinOp2->getOpcode();
451  }
452  case Stmt::CharacterLiteralClass: {
453    const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1);
454    const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2);
455    return CharLit1->getValue() == CharLit2->getValue();
456  }
457  case Stmt::DeclRefExprClass: {
458    const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1);
459    const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2);
460    return DeclRef1->getDecl() == DeclRef2->getDecl();
461  }
462  case Stmt::IntegerLiteralClass: {
463    const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1);
464    const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2);
465
466    llvm::APInt I1 = IntLit1->getValue();
467    llvm::APInt I2 = IntLit2->getValue();
468    if (I1.getBitWidth() != I2.getBitWidth())
469      return false;
470    return  I1 == I2;
471  }
472  case Stmt::FloatingLiteralClass: {
473    const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1);
474    const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2);
475    return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
476  }
477  case Stmt::StringLiteralClass: {
478    const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1);
479    const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2);
480    return StringLit1->getBytes() == StringLit2->getBytes();
481  }
482  case Stmt::MemberExprClass: {
483    const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1);
484    const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2);
485    return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
486  }
487  case Stmt::UnaryOperatorClass: {
488    const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1);
489    const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2);
490    return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
491  }
492  }
493}
494
495//===----------------------------------------------------------------------===//
496// FindIdenticalExprChecker
497//===----------------------------------------------------------------------===//
498
499namespace {
500class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
501public:
502  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
503                        BugReporter &BR) const {
504    FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
505    Visitor.TraverseDecl(const_cast<Decl *>(D));
506  }
507};
508} // end anonymous namespace
509
510void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
511  Mgr.registerChecker<FindIdenticalExprChecker>();
512}
513