Hi,

This patch makes the IdenticalExprChecker warn about code like:

if (i == 1) {
  foo1();
} else if (i == 1) {
  foo2();
}

The logic is the same as for binary operators. We only need to check the
current if statement and the following ones. Just as with the binary
operator check that will be O(n^2), but if you have a very large number
of chained if-else-if statements that might be a reason for a warning of
its own ;)

I ran scan-build on PHP and openssl and didn't notice any major increase
in build time. For PHP it took 1% longer, and openssl was 0.3% faster
with this checker enabled. That includes all other checks done by
alpha.core.IdenticalExpr.

Cheers,
Daniel Fahlgren
Index: lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp	(revision 201839)
+++ lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp	(working copy)
@@ -108,6 +108,32 @@
   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<IfStmt>(Else)) {
+      const Expr *Cond2 = I2->getCond();
+      if (isIdenticalStmt(AC->getASTContext(), Cond1, Cond2, false)) {
+        SourceRange Sr = Cond1->getSourceRange();
+        PathDiagnosticLocation ELoc = PathDiagnosticLocation::createBegin(Cond2,
+            BR.getSourceManager(), AC);
+        BR.EmitBasicReport(AC->getDecl(), Checker,
+                           "Identical conditions",
+                           categories::LogicError,
+                           "identical condition as a previous one", ELoc, Sr);
+      }
+      if (!(Else = I2->getElse()))
+        break;
+    }
+  }
+
   if (!Stmt1 || !Stmt2)
     return true;
 
Index: test/Analysis/identical-expressions.cpp
===================================================================
--- test/Analysis/identical-expressions.cpp	(revision 201839)
+++ test/Analysis/identical-expressions.cpp	(working copy)
@@ -1406,3 +1406,67 @@
     ;
 }
 #pragma clang diagnostic pop
+
+void test_warn_chained_if_stmts_1(int x) {
+  if (x == 1)
+    ;
+  else if (x == 1) // expected-warning {{identical condition as a previous one}}
+    ;
+}
+
+void test_warn_chained_if_stmts_2(int x) {
+  if (x == 1)
+    ;
+  else if (x == 1) // expected-warning {{identical condition as a previous one}}
+    ;
+  else if (x == 1) // expected-warning {{identical condition as a previous one}}
+    ;
+}
+
+void test_warn_chained_if_stmts_3(int x) {
+  if (x == 1)
+    ;
+  else if (x == 2)
+    ;
+  else if (x == 1) // expected-warning {{identical condition as a previous one}}
+    ;
+}
+
+void test_warn_chained_if_stmts_4(int x) {
+  if (x == 1)
+    ;
+  else if (func())
+    ;
+  else if (x == 1) // expected-warning {{identical condition as a previous one}}
+    ;
+}
+
+void test_warn_chained_if_stmts_5(int x) {
+  if (x & 1)
+    ;
+  else if (x & 1) // expected-warning {{identical condition as a previous one}}
+    ;
+}
+
+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
+    ;
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to