1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Added preference about macro expansion

This commit is contained in:
Alena Laskavaia 2010-05-20 02:36:53 +00:00
parent 5bd960f42a
commit 22e14a8102
5 changed files with 112 additions and 26 deletions

View file

@ -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$
public static String NamingConventionFunctionChecker_LabelNamePattern;
public static String ReturnChecker_Param0;
public static String StatementHasNoEffectChecker_ParameterMacro;
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, CheckersMessages.class);

View file

@ -10,6 +10,7 @@
*******************************************************************************/
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.model.IProblemWorkingCopy;
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 {
private 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 ER_ID = "org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem"; //$NON-NLS-1$
public static final String PARAM_MACRO_ID = "macro"; //$NON-NLS-1$
public void processAst(IASTTranslationUnit ast) {
ast.accept(new CheckStmpVisitor());
@ -52,8 +53,15 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
public int visit(IASTStatement stmt) {
if (stmt instanceof IASTExpressionStatement) {
if (hasNoEffect(((IASTExpressionStatement) stmt).getExpression())) {
reportProblem(ER_ID, stmt, stmt.getRawSignature());
IASTExpression expression = ((IASTExpressionStatement) stmt)
.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;
}
@ -71,11 +79,13 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
private boolean hasNoEffect(IASTExpression e) {
if (e instanceof IASTBinaryExpression) {
IASTBinaryExpression binExpr = (IASTBinaryExpression) e;
if (isLValue(binExpr)) return false;
if (isLValue(binExpr))
return false;
switch (binExpr.getOperator()) {
case IASTBinaryExpression.op_logicalOr:
case IASTBinaryExpression.op_logicalAnd:
return hasNoEffect(binExpr.getOperand1()) && hasNoEffect(binExpr.getOperand2());
return hasNoEffect(binExpr.getOperand1())
&& hasNoEffect(binExpr.getOperand2());
}
return true;
}
@ -102,7 +112,9 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
IASTNode parent2 = parent.getParent();
if (parent2 instanceof IASTCompoundStatement) {
IASTNode parent3 = parent2.getParent();
if (parent3 instanceof IGNUASTCompoundStatementExpression) { return false; }
if (parent3 instanceof IGNUASTCompoundStatementExpression) {
return false;
}
}
}
return true;
@ -112,7 +124,17 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
}
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")
@ -124,8 +146,7 @@ public class StatementHasNoEffectChecker extends AbstractIndexAstChecker {
ICPPFunction overload = cppBin.getOverload();
if (overload != null)
return false;
IType expressionType = cppBin.getOperand1()
.getExpressionType();
IType expressionType = cppBin.getOperand1().getExpressionType();
if (!(expressionType instanceof IBasicType)) {
return false; // must be overloaded but parser could not
// find it

View file

@ -1,2 +1,3 @@
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
ReturnChecker_Param0=Also check functions with implicit return value
StatementHasNoEffectChecker_ParameterMacro=Report problem in statements that comes from macro expansion

View file

@ -13,7 +13,12 @@ package org.eclipse.cdt.codan.core.internal.checkers;
import java.io.File;
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.internal.checkers.StatementHasNoEffectChecker;
/**
* Test for {@see StatementHasNoEffectChecker} class
@ -105,7 +110,7 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
checkErrorLine(f1, 3);
checkErrorLine(f2, 4);
}
// main() {
// for (a=b;a;a=a->next);
// }
@ -113,6 +118,7 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
loadCodeAndRun(getAboveComment());
checkNoErrors();
}
// void main() {
// bool a;
// class c {};
@ -123,7 +129,7 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
loadCodeAndRunCpp(getAboveComment());
checkNoErrors();
}
// main() {
// A a,b;
//
@ -133,4 +139,48 @@ public class StatementHasNoEffectCheckerTest extends CheckerTestCase {
loadCodeAndRun(getAboveComment());
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;
}
}

View file

@ -24,7 +24,6 @@ import org.eclipse.core.runtime.NullProgressMonitor;
*
*/
public class CheckerTestCase extends CodanTestCase {
private IMarker[] markers;
public void checkErrorLine(int i) {
@ -32,19 +31,20 @@ public class CheckerTestCase extends CodanTestCase {
}
/**
* @param i
* @param expectedLine
* - line
*/
public void checkErrorLine(File file, int i) {
public void checkErrorLine(File file, int expectedLine) {
assertTrue(markers != null);
assertTrue(markers.length > 0);
assertTrue("No problems found but should", markers.length > 0); //$NON-NLS-1$
boolean found = false;
Integer line = null;
String mfile = null;
for (int j = 0; j < markers.length; j++) {
IMarker m = markers[j];
Object line = null;
Object pos;
try {
line = m.getAttribute(IMarker.LINE_NUMBER);
line = (Integer) m.getAttribute(IMarker.LINE_NUMBER);
if (line == null || line.equals(-1)) {
pos = m.getAttribute(IMarker.CHAR_START);
line = new Integer(pos2line(((Integer) pos).intValue()));
@ -54,18 +54,24 @@ public class CheckerTestCase extends CodanTestCase {
} catch (IOException e) {
fail(e.getMessage());
}
String mfile = m.getResource().getName();
if (line.equals(i)) {
mfile = m.getResource().getName();
if (line.equals(expectedLine)) {
found = true;
if (file != null && !file.getName().equals(mfile)) found = false;
else break;
if (file != null && !file.getName().equals(mfile))
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() {
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() {
CodanRuntime.getInstance().getBuilder().processResource(cproject.getProject(), new NullProgressMonitor());
CodanRuntime
.getInstance()
.getBuilder()
.processResource(cproject.getProject(),
new NullProgressMonitor());
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) {
fail(e.getMessage());
}