diff --git a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
index de98893a7c7..f81a2b13c43 100644
--- a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
+++ b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
@@ -52,4 +52,8 @@ problem.description.AssignmentToItself = Finds expression where left and right s
checker.name.ReturnStyle = Return with parenthesis
problem.name.ReturnStyle = Return with parenthesis
problem.messagePattern.ReturnStyle = Return statement has invalid style. Return value should be surrounded by parenthesis
-problem.description.ReturnStyle = Checks for return statements that do no return the value in parenthesis. For example 'return 0;'
\ No newline at end of file
+problem.description.ReturnStyle = Checks for return statements that do no return the value in parenthesis. For example 'return 0;'
+checker.name.SuspiciousSemicolon = Suspicious semicolon
+problem.name.SuspiciousSemicolon = Suspicious semicolon
+problem.messagePattern.SuspiciousSemicolon = Suspicious semicolon
+problem.description.SuspiciousSemicolon = A semicolon is used as a null statement in a condition. For example, 'if(expression);'
\ No newline at end of file
diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
index 409cb9a7781..ab87727a4e6 100644
--- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml
+++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
@@ -278,7 +278,7 @@
name="%problem.name.AssignmentToItself">
-
@@ -291,6 +291,20 @@
messagePattern="%problem.messagePattern.ReturnStyle"
name="%problem.name.ReturnStyle">
-
+
+
+
+
+
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java
new file mode 100644
index 00000000000..3ea61391943
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuspiciousSemicolonChecker.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Marc-Andre Laperle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.internal.checkers;
+
+import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
+import org.eclipse.cdt.core.dom.ast.ASTVisitor;
+import org.eclipse.cdt.core.dom.ast.IASTFileLocation;
+import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
+import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
+import org.eclipse.cdt.core.dom.ast.IASTNullStatement;
+import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroExpansion;
+import org.eclipse.cdt.core.dom.ast.IASTStatement;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+
+public class SuspiciousSemicolonChecker extends AbstractIndexAstChecker {
+ private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"; //$NON-NLS-1$
+
+ public void processAst(IASTTranslationUnit ast) {
+ ast.accept(new ASTVisitor() {
+ {
+ shouldVisitStatements = true;
+ }
+
+ @Override
+ public int visit(IASTStatement statement) {
+ if (statement instanceof IASTIfStatement) {
+ IASTStatement thenStmt = ((IASTIfStatement) statement)
+ .getThenClause();
+ if (thenStmt instanceof IASTNullStatement
+ && noMacroInvolved(thenStmt)) {
+ reportProblem(ER_ID, thenStmt, (Object) null);
+ }
+ }
+ return PROCESS_CONTINUE;
+ }
+ });
+ }
+
+
+ protected boolean noMacroInvolved(IASTStatement node) {
+ IASTNodeSelector nodeSelector = node.getTranslationUnit()
+ .getNodeSelector(node.getTranslationUnit().getFilePath());
+ IASTFileLocation fileLocation = node.getFileLocation();
+ IASTPreprocessorMacroExpansion macro = nodeSelector
+ .findEnclosingMacroExpansion(fileLocation.getNodeOffset() - 1,
+ 1);
+ return macro == null;
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java
new file mode 100644
index 00000000000..ee0b9bf82a9
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/SuspiciousSemicolonCheckerTest.java
@@ -0,0 +1,153 @@
+/*******************************************************************************
+ * Copyright (c) 2010 Marc-Andre Laperle and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Marc-Andre Laperle - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.codan.core.internal.checkers;
+
+import org.eclipse.cdt.codan.core.test.CheckerTestCase;
+
+public class SuspiciousSemicolonCheckerTest extends CheckerTestCase {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ enableProblems("org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem"); //$NON-NLS-1$
+ }
+
+ // void foo() {
+ // if(0);
+ // }
+ public void testIf1() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2);
+ }
+
+ // void foo() {
+ // if(0);
+ // {
+ // }
+ // }
+ public void testIf2() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2);
+ }
+
+ // void foo() {
+ // if(0)
+ // foo();
+ // }
+ public void testIf3() {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrors();
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // }
+ public void testIf4() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ }
+
+ // void foo() {
+ // if(0);{
+ // }
+ // }
+ public void testIf5() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(2);
+ }
+
+ // void foo() {
+ // if(0) {};
+ // }
+ public void testIf6() {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrors();
+ }
+
+ // void foo() {
+ // if(0
+ // );
+ // }
+ // }
+ public void testIf7() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // else if(0);
+ // }
+ public void testElseIf1() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ checkErrorLine(4);
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // else if(0);
+ // {
+ //
+ // }
+ // }
+ public void testElseIf2() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ checkErrorLine(4);
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // else if(0);{
+ // }
+ // }
+ public void testElseIf3() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ checkErrorLine(4);
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // else if(0){};
+ // }
+ public void testElseIf4() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ }
+
+ // void foo() {
+ // if(0)
+ // ;
+ // else if(0
+ // );
+ // }
+ public void testElseIf5() {
+ loadCodeAndRun(getAboveComment());
+ checkErrorLine(3);
+ checkErrorLine(5);
+ }
+
+ // #define OP
+ // void foo() {
+ // if(0)
+ // OP;
+ // }
+ public void testMacro() {
+ loadCodeAndRun(getAboveComment());
+ checkNoErrors();
+ }
+}
diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
index 30d9292f6d2..119eece8c9c 100644
--- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
+++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
@@ -21,6 +21,7 @@ import org.eclipse.cdt.codan.core.internal.checkers.ReturnCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.ReturnStyleCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.StatementHasNoEffectCheckerTest;
import org.eclipse.cdt.codan.core.internal.checkers.SuggestedParenthesisCheckerTest;
+import org.eclipse.cdt.codan.core.internal.checkers.SuspiciousSemicolonCheckerTest;
import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.SuggestedParenthesisQuickFixTest;
public class AutomatedIntegrationSuite extends TestSuite {
@@ -49,6 +50,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
suite.addTestSuite(AssignmentInConditionCheckerTest.class);
suite.addTestSuite(AssignmentToItselfCheckerTest.class);
suite.addTestSuite(ReturnStyleCheckerTest.class);
+ suite.addTestSuite(SuspiciousSemicolonCheckerTest.class);
// framework
suite.addTest(CodanFastTestSuite.suite());
// quick fixes