mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 10:16:03 +02:00
Added preference about macro expansion
This commit is contained in:
parent
5bd960f42a
commit
22e14a8102
5 changed files with 112 additions and 26 deletions
|
@ -19,6 +19,7 @@ public class CheckersMessages extends NLS {
|
||||||
private static final String BUNDLE_NAME = "org.eclipse.cdt.codan.internal.checkers.messages"; //$NON-NLS-1$
|
private static final String BUNDLE_NAME = "org.eclipse.cdt.codan.internal.checkers.messages"; //$NON-NLS-1$
|
||||||
public static String NamingConventionFunctionChecker_LabelNamePattern;
|
public static String NamingConventionFunctionChecker_LabelNamePattern;
|
||||||
public static String ReturnChecker_Param0;
|
public static String ReturnChecker_Param0;
|
||||||
|
public static String StatementHasNoEffectChecker_ParameterMacro;
|
||||||
static {
|
static {
|
||||||
// initialize resource bundle
|
// initialize resource bundle
|
||||||
NLS.initializeMessages(BUNDLE_NAME, CheckersMessages.class);
|
NLS.initializeMessages(BUNDLE_NAME, CheckersMessages.class);
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.codan.internal.checkers;
|
package org.eclipse.cdt.codan.internal.checkers;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.cxx.CxxAstUtils;
|
||||||
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
|
import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker;
|
||||||
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy;
|
||||||
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
@ -38,8 +39,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem"; //$NON-NLS-1$
|
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem"; //$NON-NLS-1$
|
||||||
private static final String PARAM_MACRO_ID = "macro";
|
public static final String PARAM_MACRO_ID = "macro"; //$NON-NLS-1$
|
||||||
|
|
||||||
public void processAst(IASTTranslationUnit ast) {
|
public void processAst(IASTTranslationUnit ast) {
|
||||||
ast.accept(new CheckStmpVisitor());
|
ast.accept(new CheckStmpVisitor());
|
||||||
|
@ -52,8 +53,15 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
|
|
||||||
public int visit(IASTStatement stmt) {
|
public int visit(IASTStatement stmt) {
|
||||||
if (stmt instanceof IASTExpressionStatement) {
|
if (stmt instanceof IASTExpressionStatement) {
|
||||||
if (hasNoEffect(((IASTExpressionStatement) stmt).getExpression())) {
|
IASTExpression expression = ((IASTExpressionStatement) stmt)
|
||||||
reportProblem(ER_ID, stmt, stmt.getRawSignature());
|
.getExpression();
|
||||||
|
if (hasNoEffect(expression)) {
|
||||||
|
boolean inMacro = CxxAstUtils.getInstance().isInMacro(
|
||||||
|
expression);
|
||||||
|
boolean shouldReportInMacro = shouldReportInMacro();
|
||||||
|
if (inMacro && !shouldReportInMacro)
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
reportProblem(ER_ID, stmt, expression.getRawSignature());
|
||||||
}
|
}
|
||||||
return PROCESS_SKIP;
|
return PROCESS_SKIP;
|
||||||
}
|
}
|
||||||
|
@ -71,11 +79,13 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
private boolean hasNoEffect(IASTExpression e) {
|
private boolean hasNoEffect(IASTExpression e) {
|
||||||
if (e instanceof IASTBinaryExpression) {
|
if (e instanceof IASTBinaryExpression) {
|
||||||
IASTBinaryExpression binExpr = (IASTBinaryExpression) e;
|
IASTBinaryExpression binExpr = (IASTBinaryExpression) e;
|
||||||
if (isLValue(binExpr)) return false;
|
if (isLValue(binExpr))
|
||||||
|
return false;
|
||||||
switch (binExpr.getOperator()) {
|
switch (binExpr.getOperator()) {
|
||||||
case IASTBinaryExpression.op_logicalOr:
|
case IASTBinaryExpression.op_logicalOr:
|
||||||
case IASTBinaryExpression.op_logicalAnd:
|
case IASTBinaryExpression.op_logicalAnd:
|
||||||
return hasNoEffect(binExpr.getOperand1()) && hasNoEffect(binExpr.getOperand2());
|
return hasNoEffect(binExpr.getOperand1())
|
||||||
|
&& hasNoEffect(binExpr.getOperand2());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +112,9 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
IASTNode parent2 = parent.getParent();
|
IASTNode parent2 = parent.getParent();
|
||||||
if (parent2 instanceof IASTCompoundStatement) {
|
if (parent2 instanceof IASTCompoundStatement) {
|
||||||
IASTNode parent3 = parent2.getParent();
|
IASTNode parent3 = parent2.getParent();
|
||||||
if (parent3 instanceof IGNUASTCompoundStatementExpression) { return false; }
|
if (parent3 instanceof IGNUASTCompoundStatementExpression) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -112,7 +124,17 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initPreferences(IProblemWorkingCopy problem) {
|
public void initPreferences(IProblemWorkingCopy problem) {
|
||||||
addPreference(problem, PARAM_MACRO_ID, "Check statements that belong to macro", Boolean.TRUE);
|
addPreference(problem, PARAM_MACRO_ID,
|
||||||
|
CheckersMessages.StatementHasNoEffectChecker_ParameterMacro,
|
||||||
|
Boolean.TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean shouldReportInMacro() {
|
||||||
|
return (Boolean) getPreference(getProblemById(ER_ID, getFile()),
|
||||||
|
PARAM_MACRO_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("restriction")
|
@SuppressWarnings("restriction")
|
||||||
|
@ -124,8 +146,7 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
|
||||||
ICPPFunction overload = cppBin.getOverload();
|
ICPPFunction overload = cppBin.getOverload();
|
||||||
if (overload != null)
|
if (overload != null)
|
||||||
return false;
|
return false;
|
||||||
IType expressionType = cppBin.getOperand1()
|
IType expressionType = cppBin.getOperand1().getExpressionType();
|
||||||
.getExpressionType();
|
|
||||||
if (!(expressionType instanceof IBasicType)) {
|
if (!(expressionType instanceof IBasicType)) {
|
||||||
return false; // must be overloaded but parser could not
|
return false; // must be overloaded but parser could not
|
||||||
// find it
|
// find it
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
||||||
ReturnChecker_Param0=Also check functions with implicit return value
|
ReturnChecker_Param0=Also check functions with implicit return value
|
||||||
|
StatementHasNoEffectChecker_ParameterMacro=Report problem in statements that comes from macro expansion
|
||||||
|
|
|
@ -13,7 +13,12 @@ package org.eclipse.cdt.codan.core.internal.checkers;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.codan.core.CodanRuntime;
|
||||||
|
import org.eclipse.cdt.codan.core.model.IProblem;
|
||||||
|
import org.eclipse.cdt.codan.core.param.IProblemPreference;
|
||||||
|
import org.eclipse.cdt.codan.core.param.MapProblemPreference;
|
||||||
import org.eclipse.cdt.codan.core.test.CheckerTestCase;
|
import org.eclipse.cdt.codan.core.test.CheckerTestCase;
|
||||||
|
import org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectChecker;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test for {@see StatementHasNoEffectChecker} class
|
* Test for {@see StatementHasNoEffectChecker} class
|
||||||
|
@ -113,6 +118,7 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
// void main() {
|
// void main() {
|
||||||
// bool a;
|
// bool a;
|
||||||
// class c {};
|
// class c {};
|
||||||
|
@ -133,4 +139,48 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
|
||||||
loadCodeAndRun(getAboveComment());
|
loadCodeAndRun(getAboveComment());
|
||||||
checkNoErrors();
|
checkNoErrors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//#define FUNC(a) a
|
||||||
|
// main() {
|
||||||
|
// int a;
|
||||||
|
// FUNC(a); // error by default
|
||||||
|
// }
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public void testInMacro() {
|
||||||
|
IProblemPreference macro = getMapPreference(
|
||||||
|
StatementHasNoEffectChecker.ER_ID,
|
||||||
|
StatementHasNoEffectChecker.PARAM_MACRO_ID);
|
||||||
|
macro.setValue(Boolean.TRUE);
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkErrorLine(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#define FUNC(a) a
|
||||||
|
// main() {
|
||||||
|
// int a;
|
||||||
|
// FUNC(a); // no error if macro exp turned off
|
||||||
|
// }
|
||||||
|
@SuppressWarnings("restriction")
|
||||||
|
public void testInMacroParamOff() {
|
||||||
|
IProblemPreference macro = getMapPreference(
|
||||||
|
StatementHasNoEffectChecker.ER_ID,
|
||||||
|
StatementHasNoEffectChecker.PARAM_MACRO_ID);
|
||||||
|
macro.setValue(Boolean.FALSE);
|
||||||
|
loadCodeAndRun(getAboveComment());
|
||||||
|
checkNoErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param problemId
|
||||||
|
* @param paramId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected IProblemPreference getMapPreference(String problemId,
|
||||||
|
String paramId) {
|
||||||
|
IProblem problem = CodanRuntime.getInstance().getChechersRegistry()
|
||||||
|
.getWorkspaceProfile().findProblem(problemId);
|
||||||
|
IProblemPreference pref = ((MapProblemPreference) problem
|
||||||
|
.getPreference()).getChildDescriptor(paramId);
|
||||||
|
return pref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class CheckerTestCase extends CodanTestCase {
|
public class CheckerTestCase extends CodanTestCase {
|
||||||
|
|
||||||
private IMarker[] markers;
|
private IMarker[] markers;
|
||||||
|
|
||||||
public void checkErrorLine(int i) {
|
public void checkErrorLine(int i) {
|
||||||
|
@ -32,19 +31,20 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param i
|
* @param expectedLine
|
||||||
* - line
|
* - line
|
||||||
*/
|
*/
|
||||||
public void checkErrorLine(File file, int i) {
|
public void checkErrorLine(File file, int expectedLine) {
|
||||||
assertTrue(markers != null);
|
assertTrue(markers != null);
|
||||||
assertTrue(markers.length > 0);
|
assertTrue("No problems found but should", markers.length > 0); //$NON-NLS-1$
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
|
Integer line = null;
|
||||||
|
String mfile = null;
|
||||||
for (int j = 0; j < markers.length; j++) {
|
for (int j = 0; j < markers.length; j++) {
|
||||||
IMarker m = markers[j];
|
IMarker m = markers[j];
|
||||||
Object line = null;
|
|
||||||
Object pos;
|
Object pos;
|
||||||
try {
|
try {
|
||||||
line = m.getAttribute(IMarker.LINE_NUMBER);
|
line = (Integer) m.getAttribute(IMarker.LINE_NUMBER);
|
||||||
if (line == null || line.equals(-1)) {
|
if (line == null || line.equals(-1)) {
|
||||||
pos = m.getAttribute(IMarker.CHAR_START);
|
pos = m.getAttribute(IMarker.CHAR_START);
|
||||||
line = new Integer(pos2line(((Integer) pos).intValue()));
|
line = new Integer(pos2line(((Integer) pos).intValue()));
|
||||||
|
@ -54,18 +54,24 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
String mfile = m.getResource().getName();
|
mfile = m.getResource().getName();
|
||||||
if (line.equals(i)) {
|
if (line.equals(expectedLine)) {
|
||||||
found = true;
|
found = true;
|
||||||
if (file != null && !file.getName().equals(mfile)) found = false;
|
if (file != null && !file.getName().equals(mfile))
|
||||||
else break;
|
found = false;
|
||||||
|
else
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assertTrue("Error on line " + i + " not found ", found);
|
assertEquals(Integer.valueOf(expectedLine), line);
|
||||||
|
if (file != null)
|
||||||
|
assertEquals(file.getName(), mfile);
|
||||||
|
assertTrue(found);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void checkNoErrors() {
|
public void checkNoErrors() {
|
||||||
assertTrue("Found errors but should not", markers == null || markers.length == 0);
|
assertTrue("Found errors but should not", markers == null
|
||||||
|
|| markers.length == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,9 +100,16 @@ public class CheckerTestCase extends CodanTestCase {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected void runCodan() {
|
protected void runCodan() {
|
||||||
CodanRuntime.getInstance().getBuilder().processResource(cproject.getProject(), new NullProgressMonitor());
|
CodanRuntime
|
||||||
|
.getInstance()
|
||||||
|
.getBuilder()
|
||||||
|
.processResource(cproject.getProject(),
|
||||||
|
new NullProgressMonitor());
|
||||||
try {
|
try {
|
||||||
markers = cproject.getProject().findMarkers(IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE, true, 1);
|
markers = cproject.getProject()
|
||||||
|
.findMarkers(
|
||||||
|
IProblemReporter.GENERIC_CODE_ANALYSIS_MARKER_TYPE,
|
||||||
|
true, 1);
|
||||||
} catch (CoreException e) {
|
} catch (CoreException e) {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue