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 
26 using namespace clang;
27 using namespace ento;
28 
29 static 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 
35 namespace {
36 class FindIdenticalExprVisitor
37     : public RecursiveASTVisitor<FindIdenticalExprVisitor> {
38   BugReporter &BR;
39   const CheckerBase *Checker;
40   AnalysisDeclContext *AC;
41 public:
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 
53 private:
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 
61 void 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 
78 void 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 
107 bool FindIdenticalExprVisitor::VisitIfStmt(const IfStmt *I) {
108   const Stmt *Stmt1 = I->getThen();
109   const Stmt *Stmt2 = I->getElse();
110 
111   if (!Stmt1 || !Stmt2)
112     return true;
113 
114   // Special handling for code like:
115   //
116   // if (b) {
117   //   i = 1;
118   // } else
119   //   i = 1;
120   if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt1)) {
121     if (CompStmt->size() == 1)
122       Stmt1 = CompStmt->body_back();
123   }
124   if (const CompoundStmt *CompStmt = dyn_cast<CompoundStmt>(Stmt2)) {
125     if (CompStmt->size() == 1)
126       Stmt2 = CompStmt->body_back();
127   }
128 
129   if (isIdenticalStmt(AC->getASTContext(), Stmt1, Stmt2, true)) {
130       PathDiagnosticLocation ELoc =
131           PathDiagnosticLocation::createBegin(I, BR.getSourceManager(), AC);
132       BR.EmitBasicReport(AC->getDecl(), Checker,
133                          "Identical branches",
134                          categories::LogicError,
135                          "true and false branches are identical", ELoc);
136   }
137   return true;
138 }
139 
140 bool FindIdenticalExprVisitor::VisitBinaryOperator(const BinaryOperator *B) {
141   BinaryOperator::Opcode Op = B->getOpcode();
142 
143   if (BinaryOperator::isBitwiseOp(Op))
144     checkBitwiseOrLogicalOp(B, true);
145 
146   if (BinaryOperator::isLogicalOp(Op))
147     checkBitwiseOrLogicalOp(B, false);
148 
149   if (BinaryOperator::isComparisonOp(Op))
150     checkComparisonOp(B);
151 
152   // We want to visit ALL nodes (subexpressions of binary comparison
153   // expressions too) that contains comparison operators.
154   // True is always returned to traverse ALL nodes.
155   return true;
156 }
157 
158 void FindIdenticalExprVisitor::checkComparisonOp(const BinaryOperator *B) {
159   BinaryOperator::Opcode Op = B->getOpcode();
160 
161   //
162   // Special case for floating-point representation.
163   //
164   // If expressions on both sides of comparison operator are of type float,
165   // then for some comparison operators no warning shall be
166   // reported even if the expressions are identical from a symbolic point of
167   // view. Comparison between expressions, declared variables and literals
168   // are treated differently.
169   //
170   // != and == between float literals that have the same value should NOT warn.
171   // < > between float literals that have the same value SHOULD warn.
172   //
173   // != and == between the same float declaration should NOT warn.
174   // < > between the same float declaration SHOULD warn.
175   //
176   // != and == between eq. expressions that evaluates into float
177   //           should NOT warn.
178   // < >       between eq. expressions that evaluates into float
179   //           should NOT warn.
180   //
181   const Expr *LHS = B->getLHS()->IgnoreParenImpCasts();
182   const Expr *RHS = B->getRHS()->IgnoreParenImpCasts();
183 
184   const DeclRefExpr *DeclRef1 = dyn_cast<DeclRefExpr>(LHS);
185   const DeclRefExpr *DeclRef2 = dyn_cast<DeclRefExpr>(RHS);
186   const FloatingLiteral *FloatLit1 = dyn_cast<FloatingLiteral>(LHS);
187   const FloatingLiteral *FloatLit2 = dyn_cast<FloatingLiteral>(RHS);
188   if ((DeclRef1) && (DeclRef2)) {
189     if ((DeclRef1->getType()->hasFloatingRepresentation()) &&
190         (DeclRef2->getType()->hasFloatingRepresentation())) {
191       if (DeclRef1->getDecl() == DeclRef2->getDecl()) {
192         if ((Op == BO_EQ) || (Op == BO_NE)) {
193           return;
194         }
195       }
196     }
197   } else if ((FloatLit1) && (FloatLit2)) {
198     if (FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue())) {
199       if ((Op == BO_EQ) || (Op == BO_NE)) {
200         return;
201       }
202     }
203   } else if (LHS->getType()->hasFloatingRepresentation()) {
204     // If any side of comparison operator still has floating-point
205     // representation, then it's an expression. Don't warn.
206     // Here only LHS is checked since RHS will be implicit casted to float.
207     return;
208   } else {
209     // No special case with floating-point representation, report as usual.
210   }
211 
212   if (isIdenticalStmt(AC->getASTContext(), B->getLHS(), B->getRHS())) {
213     PathDiagnosticLocation ELoc =
214         PathDiagnosticLocation::createOperatorLoc(B, BR.getSourceManager());
215     StringRef Message;
216     if (((Op == BO_EQ) || (Op == BO_LE) || (Op == BO_GE)))
217       Message = "comparison of identical expressions always evaluates to true";
218     else
219       Message = "comparison of identical expressions always evaluates to false";
220     BR.EmitBasicReport(AC->getDecl(), Checker,
221                        "Compare of identical expressions",
222                        categories::LogicError, Message, ELoc);
223   }
224 }
225 
226 bool FindIdenticalExprVisitor::VisitConditionalOperator(
227     const ConditionalOperator *C) {
228 
229   // Check if expressions in conditional expression are identical
230   // from a symbolic point of view.
231 
232   if (isIdenticalStmt(AC->getASTContext(), C->getTrueExpr(),
233                       C->getFalseExpr(), true)) {
234     PathDiagnosticLocation ELoc =
235         PathDiagnosticLocation::createConditionalColonLoc(
236             C, BR.getSourceManager());
237 
238     SourceRange Sr[2];
239     Sr[0] = C->getTrueExpr()->getSourceRange();
240     Sr[1] = C->getFalseExpr()->getSourceRange();
241     BR.EmitBasicReport(
242         AC->getDecl(), Checker,
243         "Identical expressions in conditional expression",
244         categories::LogicError,
245         "identical expressions on both sides of ':' in conditional expression",
246         ELoc, Sr);
247   }
248   // We want to visit ALL nodes (expressions in conditional
249   // expressions too) that contains conditional operators,
250   // thus always return true to traverse ALL nodes.
251   return true;
252 }
253 
254 /// \brief Determines whether two statement trees are identical regarding
255 /// operators and symbols.
256 ///
257 /// Exceptions: expressions containing macros or functions with possible side
258 /// effects are never considered identical.
259 /// Limitations: (t + u) and (u + t) are not considered identical.
260 /// t*(u + t) and t*u + t*t are not considered identical.
261 ///
262 static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
263                             const Stmt *Stmt2, bool IgnoreSideEffects) {
264 
265   if (!Stmt1 || !Stmt2) {
266     if (!Stmt1 && !Stmt2)
267       return true;
268     return false;
269   }
270 
271   // If Stmt1 & Stmt2 are of different class then they are not
272   // identical statements.
273   if (Stmt1->getStmtClass() != Stmt2->getStmtClass())
274     return false;
275 
276   const Expr *Expr1 = dyn_cast<Expr>(Stmt1);
277   const Expr *Expr2 = dyn_cast<Expr>(Stmt2);
278 
279   if (Expr1 && Expr2) {
280     // If Stmt1 has side effects then don't warn even if expressions
281     // are identical.
282     if (!IgnoreSideEffects && Expr1->HasSideEffects(Ctx))
283       return false;
284     // If either expression comes from a macro then don't warn even if
285     // the expressions are identical.
286     if ((Expr1->getExprLoc().isMacroID()) || (Expr2->getExprLoc().isMacroID()))
287       return false;
288 
289     // If all children of two expressions are identical, return true.
290     Expr::const_child_iterator I1 = Expr1->child_begin();
291     Expr::const_child_iterator I2 = Expr2->child_begin();
292     while (I1 != Expr1->child_end() && I2 != Expr2->child_end()) {
293       if (!*I1 || !*I2 || !isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
294         return false;
295       ++I1;
296       ++I2;
297     }
298     // If there are different number of children in the statements, return
299     // false.
300     if (I1 != Expr1->child_end())
301       return false;
302     if (I2 != Expr2->child_end())
303       return false;
304   }
305 
306   switch (Stmt1->getStmtClass()) {
307   default:
308     return false;
309   case Stmt::CallExprClass:
310   case Stmt::ArraySubscriptExprClass:
311   case Stmt::ImplicitCastExprClass:
312   case Stmt::ParenExprClass:
313   case Stmt::BreakStmtClass:
314   case Stmt::ContinueStmtClass:
315   case Stmt::NullStmtClass:
316     return true;
317   case Stmt::CStyleCastExprClass: {
318     const CStyleCastExpr* CastExpr1 = cast<CStyleCastExpr>(Stmt1);
319     const CStyleCastExpr* CastExpr2 = cast<CStyleCastExpr>(Stmt2);
320 
321     return CastExpr1->getTypeAsWritten() == CastExpr2->getTypeAsWritten();
322   }
323   case Stmt::ReturnStmtClass: {
324     const ReturnStmt *ReturnStmt1 = cast<ReturnStmt>(Stmt1);
325     const ReturnStmt *ReturnStmt2 = cast<ReturnStmt>(Stmt2);
326 
327     return isIdenticalStmt(Ctx, ReturnStmt1->getRetValue(),
328                            ReturnStmt2->getRetValue(), IgnoreSideEffects);
329   }
330   case Stmt::ForStmtClass: {
331     const ForStmt *ForStmt1 = cast<ForStmt>(Stmt1);
332     const ForStmt *ForStmt2 = cast<ForStmt>(Stmt2);
333 
334     if (!isIdenticalStmt(Ctx, ForStmt1->getInit(), ForStmt2->getInit(),
335                          IgnoreSideEffects))
336       return false;
337     if (!isIdenticalStmt(Ctx, ForStmt1->getCond(), ForStmt2->getCond(),
338                          IgnoreSideEffects))
339       return false;
340     if (!isIdenticalStmt(Ctx, ForStmt1->getInc(), ForStmt2->getInc(),
341                          IgnoreSideEffects))
342       return false;
343     if (!isIdenticalStmt(Ctx, ForStmt1->getBody(), ForStmt2->getBody(),
344                          IgnoreSideEffects))
345       return false;
346     return true;
347   }
348   case Stmt::DoStmtClass: {
349     const DoStmt *DStmt1 = cast<DoStmt>(Stmt1);
350     const DoStmt *DStmt2 = cast<DoStmt>(Stmt2);
351 
352     if (!isIdenticalStmt(Ctx, DStmt1->getCond(), DStmt2->getCond(),
353                          IgnoreSideEffects))
354       return false;
355     if (!isIdenticalStmt(Ctx, DStmt1->getBody(), DStmt2->getBody(),
356                          IgnoreSideEffects))
357       return false;
358     return true;
359   }
360   case Stmt::WhileStmtClass: {
361     const WhileStmt *WStmt1 = cast<WhileStmt>(Stmt1);
362     const WhileStmt *WStmt2 = cast<WhileStmt>(Stmt2);
363 
364     if (!isIdenticalStmt(Ctx, WStmt1->getCond(), WStmt2->getCond(),
365                          IgnoreSideEffects))
366       return false;
367     if (!isIdenticalStmt(Ctx, WStmt1->getBody(), WStmt2->getBody(),
368                          IgnoreSideEffects))
369       return false;
370     return true;
371   }
372   case Stmt::IfStmtClass: {
373     const IfStmt *IStmt1 = cast<IfStmt>(Stmt1);
374     const IfStmt *IStmt2 = cast<IfStmt>(Stmt2);
375 
376     if (!isIdenticalStmt(Ctx, IStmt1->getCond(), IStmt2->getCond(),
377                          IgnoreSideEffects))
378       return false;
379     if (!isIdenticalStmt(Ctx, IStmt1->getThen(), IStmt2->getThen(),
380                          IgnoreSideEffects))
381       return false;
382     if (!isIdenticalStmt(Ctx, IStmt1->getElse(), IStmt2->getElse(),
383                          IgnoreSideEffects))
384       return false;
385     return true;
386   }
387   case Stmt::CompoundStmtClass: {
388     const CompoundStmt *CompStmt1 = cast<CompoundStmt>(Stmt1);
389     const CompoundStmt *CompStmt2 = cast<CompoundStmt>(Stmt2);
390 
391     if (CompStmt1->size() != CompStmt2->size())
392       return false;
393 
394     CompoundStmt::const_body_iterator I1 = CompStmt1->body_begin();
395     CompoundStmt::const_body_iterator I2 = CompStmt2->body_begin();
396     while (I1 != CompStmt1->body_end() && I2 != CompStmt2->body_end()) {
397       if (!isIdenticalStmt(Ctx, *I1, *I2, IgnoreSideEffects))
398         return false;
399       ++I1;
400       ++I2;
401     }
402 
403     return true;
404   }
405   case Stmt::CompoundAssignOperatorClass:
406   case Stmt::BinaryOperatorClass: {
407     const BinaryOperator *BinOp1 = cast<BinaryOperator>(Stmt1);
408     const BinaryOperator *BinOp2 = cast<BinaryOperator>(Stmt2);
409     return BinOp1->getOpcode() == BinOp2->getOpcode();
410   }
411   case Stmt::CharacterLiteralClass: {
412     const CharacterLiteral *CharLit1 = cast<CharacterLiteral>(Stmt1);
413     const CharacterLiteral *CharLit2 = cast<CharacterLiteral>(Stmt2);
414     return CharLit1->getValue() == CharLit2->getValue();
415   }
416   case Stmt::DeclRefExprClass: {
417     const DeclRefExpr *DeclRef1 = cast<DeclRefExpr>(Stmt1);
418     const DeclRefExpr *DeclRef2 = cast<DeclRefExpr>(Stmt2);
419     return DeclRef1->getDecl() == DeclRef2->getDecl();
420   }
421   case Stmt::IntegerLiteralClass: {
422     const IntegerLiteral *IntLit1 = cast<IntegerLiteral>(Stmt1);
423     const IntegerLiteral *IntLit2 = cast<IntegerLiteral>(Stmt2);
424     return IntLit1->getValue() == IntLit2->getValue();
425   }
426   case Stmt::FloatingLiteralClass: {
427     const FloatingLiteral *FloatLit1 = cast<FloatingLiteral>(Stmt1);
428     const FloatingLiteral *FloatLit2 = cast<FloatingLiteral>(Stmt2);
429     return FloatLit1->getValue().bitwiseIsEqual(FloatLit2->getValue());
430   }
431   case Stmt::StringLiteralClass: {
432     const StringLiteral *StringLit1 = cast<StringLiteral>(Stmt1);
433     const StringLiteral *StringLit2 = cast<StringLiteral>(Stmt2);
434     return StringLit1->getString() == StringLit2->getString();
435   }
436   case Stmt::MemberExprClass: {
437     const MemberExpr *MemberStmt1 = cast<MemberExpr>(Stmt1);
438     const MemberExpr *MemberStmt2 = cast<MemberExpr>(Stmt2);
439     return MemberStmt1->getMemberDecl() == MemberStmt2->getMemberDecl();
440   }
441   case Stmt::UnaryOperatorClass: {
442     const UnaryOperator *UnaryOp1 = cast<UnaryOperator>(Stmt1);
443     const UnaryOperator *UnaryOp2 = cast<UnaryOperator>(Stmt2);
444     return UnaryOp1->getOpcode() == UnaryOp2->getOpcode();
445   }
446   }
447 }
448 
449 //===----------------------------------------------------------------------===//
450 // FindIdenticalExprChecker
451 //===----------------------------------------------------------------------===//
452 
453 namespace {
454 class FindIdenticalExprChecker : public Checker<check::ASTCodeBody> {
455 public:
456   void checkASTCodeBody(const Decl *D, AnalysisManager &Mgr,
457                         BugReporter &BR) const {
458     FindIdenticalExprVisitor Visitor(BR, this, Mgr.getAnalysisDeclContext(D));
459     Visitor.TraverseDecl(const_cast<Decl *>(D));
460   }
461 };
462 } // end anonymous namespace
463 
464 void ento::registerIdenticalExprChecker(CheckerManager &Mgr) {
465   Mgr.registerChecker<FindIdenticalExprChecker>();
466 }
467