19a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//== IdenticalExprChecker.cpp - Identical expression checker----------------==//
29a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//
39a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//                     The LLVM Compiler Infrastructure
49a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//
59a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose// This file is distributed under the University of Illinois Open Source
69a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose// License. See LICENSE.TXT for details.
79a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//
89a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
99a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose///
109a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// \file
119a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// \brief This defines IdenticalExprChecker, a check that warns about
129a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// unintended use of identical expressions.
139a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose///
14651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// It checks for use of identical expressions with comparison operators and
15651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// inside conditional expressions.
169a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose///
179a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
189a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
199a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose#include "ClangSACheckers.h"
20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "clang/AST/RecursiveASTVisitor.h"
219a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
229a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose#include "clang/StaticAnalyzer/Core/Checker.h"
239a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose#include "clang/StaticAnalyzer/Core/CheckerManager.h"
249a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
259a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
269a7a568821b85cc83b80056268ef0dc32aecea12Jordan Roseusing namespace clang;
279a7a568821b85cc83b80056268ef0dc32aecea12Jordan Roseusing namespace ento;
289a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
29651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
30651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            const Stmt *Stmt2, bool IgnoreSideEffects = false);
319a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
329a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose// FindIdenticalExprVisitor - Identify nodes using identical expressions.
339a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
349a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
3591934df3ce399e5938695b939943f92e7ff00483Benjamin Kramernamespace {
369a7a568821b85cc83b80056268ef0dc32aecea12Jordan Roseclass FindIdenticalExprVisitor
379a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
38651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  BugReporter &BR;
39651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const CheckerBase *Checker;
40651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  AnalysisDeclContext *AC;
419a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rosepublic:
42651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  explicit FindIdenticalExprVisitor(BugReporter &B,
43651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                    const CheckerBase *Checker,
44651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                    AnalysisDeclContext *A)
45651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      : BR(B), Checker(Checker), AC(A) {}
469a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // FindIdenticalExprVisitor only visits nodes
47651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // that are binary operators, if statements or
48651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // conditional operators.
499a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  bool VisitBinaryOperator(const BinaryOperator *B);
50651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool VisitIfStmt(const IfStmt *I);
51651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  bool VisitConditionalOperator(const ConditionalOperator *C);
529a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
539a7a568821b85cc83b80056268ef0dc32aecea12Jordan Roseprivate:
54651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void reportIdenticalExpr(const BinaryOperator *B, bool CheckBitwise,
55651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           ArrayRef<SourceRange> Sr);
56651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void checkBitwiseOrLogicalOp(const BinaryOperator *B, bool CheckBitwise);
57651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  void checkComparisonOp(const BinaryOperator *B);
589a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose};
5991934df3ce399e5938695b939943f92e7ff00483Benjamin Kramer} // end anonymous namespace
609a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
61651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid FindIdenticalExprVisitor::reportIdenticalExpr(const BinaryOperator *B,
62651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                   bool CheckBitwise,
63651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                   ArrayRef<SourceRange> Sr) {
64651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  StringRef Message;
65651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (CheckBitwise)
66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Message = "identical expressions on both sides of bitwise operator";
67651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  else
68651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Message = "identical expressions on both sides of logical operator";
69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
70651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  PathDiagnosticLocation ELoc =
71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  BR.EmitBasicReport(AC->getDecl(), Checker,
73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                     "Use of identical expressions",
74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                     categories::LogicError,
75651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                     Message, ELoc, Sr);
76651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
77651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
78651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid FindIdenticalExprVisitor::checkBitwiseOrLogicalOp(const BinaryOperator *B,
79651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                                                       bool CheckBitwise) {
80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  SourceRange Sr[2];
81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Expr *LHS = B->getLHS();
83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Expr *RHS = B->getRHS();
84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
85651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Split operators as long as we still have operators to split on. We will
86651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // get called for every binary operator in an expression so there is no need
87651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // to check every one against each other here, just the right most one with
88651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // the others.
89651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  while (const BinaryOperator *B2 = dyn_cast<BinaryOperator>(LHS)) {
90651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (B->getOpcode() != B2->getOpcode())
91651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      break;
92651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (isIdenticalStmt(AC->getASTContext(), RHS, B2->getRHS())) {
93651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Sr[0] = RHS->getSourceRange();
94651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Sr[1] = B2->getRHS()->getSourceRange();
95651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      reportIdenticalExpr(B, CheckBitwise, Sr);
96651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
97651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    LHS = B2->getLHS();
98651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
99651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
100651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isIdenticalStmt(AC->getASTContext(), RHS, LHS)) {
101651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Sr[0] = RHS->getSourceRange();
102651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Sr[1] = LHS->getSourceRange();
103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    reportIdenticalExpr(B, CheckBitwise, Sr);
104651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
105651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
106651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
107651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
108651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Stmt *Stmt1 = I->getThen();
109651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Stmt *Stmt2 = I->getElse();
110651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
111651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Check for identical conditions:
112651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //
113651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // if (b) {
114651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //   foo1();
115651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // } else if (b) {
116651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //   foo2();
117651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // }
118651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Stmt1 && Stmt2) {
119651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const Expr *Cond1 = I->getCond();
120651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const Stmt *Else = Stmt2;
121651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
122651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      const Expr *Cond2 = I2->getCond();
123651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
124651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        SourceRange Sr = Cond1->getSourceRange();
125651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
126651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           categories::LogicError,
128651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           "expression is identical to previous condition",
129651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           ELoc, Sr);
130651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      }
131651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Else = I2->getElse();
132651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
133651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
134651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
135651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!Stmt1 || !Stmt2)
136651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
137651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
138651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Special handling for code like:
139651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //
140651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // if (b) {
141651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //   i = 1;
142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // } else
143651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  //   i = 1;
144651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) {
145651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CompStmt->size() == 1)
146651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Stmt1 = CompStmt->body_back();
147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) {
149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CompStmt->size() == 1)
150651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      Stmt2 = CompStmt->body_back();
151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
153651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) {
154651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      PathDiagnosticLocation ELoc =
155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC);
156651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      BR.EmitBasicReport(AC->getDecl(), Checker,
157651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "Identical branches",
158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         categories::LogicError,
159651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         "true and false branches are identical", ELoc);
160651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
161651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return true;
162651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1649a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rosebool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
1659a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  BinaryOperator::Opcode Op = B->getOpcode();
166651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
167651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (BinaryOperator::isBitwiseOp(Op))
168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    checkBitwiseOrLogicalOp(B, true);
169651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
170651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (BinaryOperator::isLogicalOp(Op))
171651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    checkBitwiseOrLogicalOp(B, false);
172651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
173651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (BinaryOperator::isComparisonOp(Op))
174651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    checkComparisonOp(B);
175651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // We want to visit ALL nodes (subexpressions of binary comparison
177651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // expressions too) that contains comparison operators.
178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // True is always returned to traverse ALL nodes.
179651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  return true;
180651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
181651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
182651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesvoid FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
183651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  BinaryOperator::Opcode Op = B->getOpcode();
184651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
1859a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
1869a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // Special case for floating-point representation.
1879a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
1889a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // If expressions on both sides of comparison operator are of type float,
1899a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // then for some comparison operators no warning shall be
1909a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // reported even if the expressions are identical from a symbolic point of
1919a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // view. Comparison between expressions, declared variables and literals
1929a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // are treated differently.
1939a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
1949a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // != and == between float literals that have the same value should NOT warn.
1959a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // < > between float literals that have the same value SHOULD warn.
1969a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
1979a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // != and == between the same float declaration should NOT warn.
1989a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // < > between the same float declaration SHOULD warn.
1999a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
2009a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // != and == between eq. expressions that evaluates into float
2019a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //           should NOT warn.
2029a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  // < >       between eq. expressions that evaluates into float
2039a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //           should NOT warn.
2049a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  //
2059a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
2069a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();
2079a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
2089a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
2099a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
2109a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
2119a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
2129a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  if ((DeclRef1) && (DeclRef2)) {
2139a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
2149a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose        (DeclRef2->getType()->hasFloatingRepresentation())) {
2159a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
2169a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose        if ((Op == BO_EQ) || (Op == BO_NE)) {
217651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines          return;
2189a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose        }
2199a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      }
2209a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    }
2219a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  } else if ((FloatLit1) && (FloatLit2)) {
2229a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
2239a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      if ((Op == BO_EQ) || (Op == BO_NE)) {
224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return;
2259a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      }
2269a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    }
2279a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  } else if (LHS->getType()->hasFloatingRepresentation()) {
2289a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    // If any side of comparison operator still has floating-point
2299a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    // representation, then it's an expression. Don't warn.
2309a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    // Here only LHS is checked since RHS will be implicit casted to float.
231651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return;
2329a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  } else {
2339a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    // No special case with floating-point representation, report as usual.
2349a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
2359a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
236651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) {
2379a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    PathDiagnosticLocation ELoc =
2389a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose        PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
2399a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    StringRef Message;
2409a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
2419a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      Message = "comparison of identical expressions always evaluates to true";
2429a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    else
2439a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose      Message = "comparison of identical expressions always evaluates to false";
244651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BR.EmitBasicReport(AC->getDecl(), Checker,
245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                       "Compare of identical expressions",
2469a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose                       categories::LogicError, Message, ELoc);
2479a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines}
249651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
250651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesbool FindIdenticalExprVisitor::VisitConditionalOperator(
251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ConditionalOperator *C) {
252651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // Check if expressions in conditional expression are identical
254651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // from a symbolic point of view.
255651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(),
257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                      C->getFalseExpr(), true)) {
258651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    PathDiagnosticLocation ELoc =
259651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        PathDiagnosticLocation::createConditionalColonLoc(
260651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines            C, BR.getSourceManager());
261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
262651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    SourceRange Sr[2];
263651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Sr[0] = C->getTrueExpr()->getSourceRange();
264651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Sr[1] = C->getFalseExpr()->getSourceRange();
265651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    BR.EmitBasicReport(
266651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        AC->getDecl(), Checker,
267651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        "Identical expressions in conditional expression",
268651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        categories::LogicError,
269651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        "identical expressions on both sides of ':' in conditional expression",
270651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        ELoc, Sr);
271651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
272651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // We want to visit ALL nodes (expressions in conditional
273651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // expressions too) that contains conditional operators,
274651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // thus always return true to traverse ALL nodes.
2759a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  return true;
2769a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose}
277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines/// \brief Determines whether two statement trees are identical regarding
2799a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// operators and symbols.
2809a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose///
2819a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// Exceptions: expressions containing macros or functions with possible side
2829a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// effects are never considered identical.
2839a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// Limitations: (t + u) and (u + t) are not considered identical.
2849a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose/// t*(u + t) and t*u + t*t are not considered identical.
2859a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose///
286651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesstatic bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                            const Stmt *Stmt2, bool IgnoreSideEffects) {
288651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
289651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (!Stmt1 || !Stmt2) {
290651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!Stmt1 && !Stmt2)
291651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return true;
2929a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return false;
293651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
294651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
295651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // If Stmt1 & Stmt2 are of different class then they are not
296651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  // identical statements.
297651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
2989a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return false;
2999a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
300651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Expr *Expr1 = dyn_cast<Expr>(Stmt1);
301651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  const Expr *Expr2 = dyn_cast<Expr>(Stmt2);
302651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
303651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  if (Expr1 && Expr2) {
304651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If Stmt1 has side effects then don't warn even if expressions
305651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // are identical.
306651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx))
307651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
308651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If either expression comes from a macro then don't warn even if
309651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // the expressions are identical.
310651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
311651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
312651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
313651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If all children of two expressions are identical, return true.
314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Expr::const_child_iterator I1 = Expr1->child_begin();
315651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    Expr::const_child_iterator I2 = Expr2->child_begin();
316651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
317651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
318651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return false;
319651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I1;
320651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I2;
321651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
322651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // If there are different number of children in the statements, return
323651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    // false.
324651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (I1 != Expr1->child_end())
325651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
326651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (I2 != Expr2->child_end())
327651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
328651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
329651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
330651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  switch (Stmt1->getStmtClass()) {
3319a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  default:
3329a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return false;
333651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::CallExprClass:
3349a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::ArraySubscriptExprClass:
3359a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::ImplicitCastExprClass:
3369a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::ParenExprClass:
337651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::BreakStmtClass:
338651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::ContinueStmtClass:
339651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::NullStmtClass:
340651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
341651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::CStyleCastExprClass: {
342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1);
343651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2);
344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::ReturnStmtClass: {
348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
349651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
350651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
351651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(),
352651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                           ReturnStmt2->getRetValue(), IgnoreSideEffects);
353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
354651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::ForStmtClass: {
355651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1);
356651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2);
357651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
358651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(),
359651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
360651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
361651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(),
362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
363651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
364651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(),
365651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
366651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
367651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(),
368651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
369651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
370651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
371651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
372651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::DoStmtClass: {
373651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const DoStmt *DStmt1 = cast<DoStmt>(Stmt1);
374651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const DoStmt *DStmt2 = cast<DoStmt>(Stmt2);
375651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
376651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(),
377651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
379651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(),
380651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
381651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
382651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
383651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
384651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::WhileStmtClass: {
385651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1);
386651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2);
387651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
388651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(),
389651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
390651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
391651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(),
392651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
393651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
3949a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return true;
395651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
396651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::IfStmtClass: {
397651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const IfStmt *IStmt1 = cast<IfStmt>(Stmt1);
398651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const IfStmt *IStmt2 = cast<IfStmt>(Stmt2);
399651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
400651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(),
401651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
402651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
403651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(),
404651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
405651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
406651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(),
407651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines                         IgnoreSideEffects))
408651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
409651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
410651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
411651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::CompoundStmtClass: {
412651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1);
413651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2);
414651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
415651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    if (CompStmt1->size() != CompStmt2->size())
416651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      return false;
417651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
418651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin();
419651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin();
420651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) {
421651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
422651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines        return false;
423651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I1;
424651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines      ++I2;
425651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    }
426651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines
427651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return true;
428651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
429651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::CompoundAssignOperatorClass:
4309a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::BinaryOperatorClass: {
431651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1);
432651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2);
4339a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return BinOp1->getOpcode() == BinOp2->getOpcode();
4349a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4359a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::CharacterLiteralClass: {
436651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1);
437651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2);
4389a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return CharLit1->getValue() == CharLit2->getValue();
4399a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4409a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::DeclRefExprClass: {
441651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1);
442651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2);
4439a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return DeclRef1->getDecl() == DeclRef2->getDecl();
4449a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4459a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::IntegerLiteralClass: {
446651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1);
447651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2);
4489a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return IntLit1->getValue() == IntLit2->getValue();
4499a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4509a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::FloatingLiteralClass: {
451651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1);
452651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2);
4539a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
4549a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
455651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  case Stmt::StringLiteralClass: {
456651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1);
457651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2);
458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return StringLit1->getString() == StringLit2->getString();
459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines  }
4609a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::MemberExprClass: {
461651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1);
462651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2);
463651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
4649a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4659a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  case Stmt::UnaryOperatorClass: {
466651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1);
467651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2);
468651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
4699a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4709a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4719a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose}
4729a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
4739a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
4749a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose// FindIdenticalExprChecker
4759a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose//===----------------------------------------------------------------------===//
4769a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
47791934df3ce399e5938695b939943f92e7ff00483Benjamin Kramernamespace {
4789a7a568821b85cc83b80056268ef0dc32aecea12Jordan Roseclass FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
4799a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rosepublic:
4809a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
4819a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose                        BugReporter &BR) const {
482651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines    FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
4839a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose    Visitor.TraverseDecl(const_cast<Decl *>(D));
4849a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  }
4859a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose};
48691934df3ce399e5938695b939943f92e7ff00483Benjamin Kramer} // end anonymous namespace
4879a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose
4889a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rosevoid ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
4899a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose  Mgr.registerChecker<FindIdenticalExprChecker>();
4909a7a568821b85cc83b80056268ef0dc32aecea12Jordan Rose}
491