r203585 - [analyzer] Check all conditions in a chained if against each other.

Jordan Rose jordan_rose at apple.com
Tue Mar 11 09:52:29 PDT 2014


Author: jrose
Date: Tue Mar 11 11:52:29 2014
New Revision: 203585

URL: http://llvm.org/viewvc/llvm-project?rev=203585&view=rev
Log:
[analyzer] Check all conditions in a chained if against each other.

Like the binary operator check of r201702, this actually checks the
condition of every if in a chain against every other condition, an
O(N^2) operation. In most cases N should be small enough to make this
practical, and checking all cases like this makes it much more likely
to catch a copy-paste error within the same series of branches.

Part of IdenticalExprChecker; patch by Daniel Fahlgren!

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
    cfe/trunk/test/Analysis/identical-expressions.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp?rev=203585&r1=203584&r2=203585&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp Tue Mar 11 11:52:29 2014
@@ -108,6 +108,30 @@ bool FindIdenticalExprVisitor::VisitIfSt
   const Stmt *Stmt1 = I->getThen();
   const Stmt *Stmt2 = I->getElse();
 
+  // Check for identical conditions:
+  //
+  // if (b) {
+  //   foo1();
+  // } else if (b) {
+  //   foo2();
+  // }
+  if (Stmt1 && Stmt2) {
+    const Expr *Cond1 = I->getCond();
+    const Stmt *Else = Stmt2;
+    while (const IfStmt *I2 = dyn_cast_or_null<IfStmt>(Else)) {
+      const Expr *Cond2 = I2->getCond();
+      if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
+        SourceRange Sr = Cond1->getSourceRange();
+        PathDiagnosticLocation ELoc(Cond2, BR.getSourceManager(), AC);
+        BR.EmitBasicReport(AC->getDecl(), Checker, "Identical conditions",
+                           categories::LogicError,
+                           "expression is identical to previous condition",
+                           ELoc, Sr);
+      }
+      Else = I2->getElse();
+    }
+  }
+
   if (!Stmt1 || !Stmt2)
     return true;
 

Modified: cfe/trunk/test/Analysis/identical-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/identical-expressions.cpp?rev=203585&r1=203584&r2=203585&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/identical-expressions.cpp (original)
+++ cfe/trunk/test/Analysis/identical-expressions.cpp Tue Mar 11 11:52:29 2014
@@ -1406,3 +1406,108 @@ void test_identical_logical9(int x, int
     ;
 }
 #pragma clang diagnostic pop
+
+void test_warn_chained_if_stmts_1(int x) {
+  if (x == 1)
+    ;
+  else if (x == 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+}
+
+void test_warn_chained_if_stmts_2(int x) {
+  if (x == 1)
+    ;
+  else if (x == 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+  else if (x == 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+}
+
+void test_warn_chained_if_stmts_3(int x) {
+  if (x == 1)
+    ;
+  else if (x == 2)
+    ;
+  else if (x == 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+}
+
+void test_warn_chained_if_stmts_4(int x) {
+  if (x == 1)
+    ;
+  else if (func())
+    ;
+  else if (x == 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+}
+
+void test_warn_chained_if_stmts_5(int x) {
+  if (x & 1)
+    ;
+  else if (x & 1) // expected-warning {{expression is identical to previous condition}}
+    ;
+}
+
+void test_warn_chained_if_stmts_6(int x) {
+  if (x == 1)
+    ;
+  else if (x == 2)
+    ;
+  else if (x == 2) // expected-warning {{expression is identical to previous condition}}
+    ;
+  else if (x == 3)
+    ;
+}
+
+void test_warn_chained_if_stmts_7(int x) {
+  if (x == 1)
+    ;
+  else if (x == 2)
+    ;
+  else if (x == 3)
+    ;
+  else if (x == 2) // expected-warning {{expression is identical to previous condition}}
+    ;
+  else if (x == 5)
+    ;
+}
+
+void test_warn_chained_if_stmts_8(int x) {
+  if (x == 1)
+    ;
+  else if (x == 2)
+    ;
+  else if (x == 3)
+    ;
+  else if (x == 2) // expected-warning {{expression is identical to previous condition}}
+    ;
+  else if (x == 5)
+    ;
+  else if (x == 3) // expected-warning {{expression is identical to previous condition}}
+    ;
+  else if (x == 7)
+    ;
+}
+
+void test_nowarn_chained_if_stmts_1(int x) {
+  if (func())
+    ;
+  else if (func()) // no-warning
+    ;
+}
+
+void test_nowarn_chained_if_stmts_2(int x) {
+  if (func())
+    ;
+  else if (x == 1)
+    ;
+  else if (func()) // no-warning
+    ;
+}
+
+void test_nowarn_chained_if_stmts_3(int x) {
+  if (x++)
+    ;
+  else if (x++) // no-warning
+    ;
+}





More information about the cfe-commits mailing list