diff options
author | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
---|---|---|
committer | Elliott Baron <ebaron@fedoraproject.org> | 2010-06-26 22:27:34 -0400 |
commit | 4e112eca7750a4f530c986be55c178c43c16d3ea (patch) | |
tree | db140c4fe4db9945502398e4869707ca0346353e /org.eclipse.cdt.codan.checkers/src/org/eclipse | |
parent | aa73b3f2503808e4b4029a73368a75b258d6f0dc (diff) | |
download | codan-master.tar.gz codan-master.tar.xz codan-master.zip |
* org.eclipse.cdt.codan.checkers.ui: Updated.
* org.eclipse.cdt.codan.checkers: Updated.
* org.eclipse.cdt.codan.core: Updated.
* org.eclipse.cdt.codan.ui: Updated.
* org.eclipse.cdt.codan.core.cxx: Added.
* org.eclipse.cdt.codan.extension/META-INF/MANIFEST.MF: Import org.eclipse.cdt.codan.core.cxx.model.
* org.eclipse.cdt.codan.extension/src/org/eclipse/cdt/codan/extension/checkers/AbstractPropSimChecker.java: Superclass moved.
Diffstat (limited to 'org.eclipse.cdt.codan.checkers/src/org/eclipse')
29 files changed, 804 insertions, 288 deletions
diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/CVS/Tag new file mode 100644 index 0000000..3cd1ca4 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/CVS/Tag @@ -0,0 +1 @@ +TCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/CVS/Tag new file mode 100644 index 0000000..3cd1ca4 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/CVS/Tag @@ -0,0 +1 @@ +TCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Entries b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Entries index 513604d..83a5699 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Entries +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Entries @@ -1 +1,3 @@ D/checkers//// +D/examples//// +D/internal//// diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Tag new file mode 100644 index 0000000..3cd1ca4 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/CVS/Tag @@ -0,0 +1 @@ +TCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Entries b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Entries index 0f9ebcd..2c318af 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Entries +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Entries @@ -1,2 +1,2 @@ -/Activator.java/1.3/Sat May 9 01:36:37 2009// +/CodanCheckersActivator.java/1.3/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 D/sample//// diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Tag new file mode 100644 index 0000000..49a449a --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CVS/Tag @@ -0,0 +1 @@ +NCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/Activator.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CodanCheckersActivator.java index 2915e7d..c2e21c3 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/Activator.java +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/CodanCheckersActivator.java @@ -1,3 +1,13 @@ +/******************************************************************************* + * Copyright (c) 2010 Alena Laskavaia 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ package org.eclipse.cdt.codan.checkers; import org.eclipse.core.runtime.IStatus; @@ -8,16 +18,16 @@ import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ -public class Activator extends Plugin { +public class CodanCheckersActivator extends Plugin { // The plug-in ID - public static final String PLUGIN_ID = "org.eclipse.cdt.codan.checkers"; + public static final String PLUGIN_ID = "org.eclipse.cdt.codan.checkers"; //$NON-NLS-1$ // The shared instance - private static Activator plugin; + private static CodanCheckersActivator plugin; /** * The constructor */ - public Activator() { + public CodanCheckersActivator() { } /* @@ -49,7 +59,7 @@ public class Activator extends Plugin { * * @return the shared instance */ - public static Activator getDefault() { + public static CodanCheckersActivator getDefault() { return plugin; } diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Entries b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Entries deleted file mode 100644 index 705d9ab..0000000 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Entries +++ /dev/null @@ -1,5 +0,0 @@ -/AssignmentInConditionChecker.java/1.4/Fri Jul 31 20:39:13 2009// -/CatchUsesReference.java/1.2/Sat Nov 21 02:25:12 2009// -/NonVirtualDestructor.java/1.4/Fri Jul 31 20:39:13 2009// -/StatementHasNoEffectChecker.java/1.5/Fri Jul 31 20:39:13 2009// -/SuggestedParenthesisChecker.java/1.2/Sat Nov 21 03:03:08 2009// diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CatchUsesReference.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CatchUsesReference.java deleted file mode 100644 index b3556cc..0000000 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CatchUsesReference.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009 Alena Laskavaia - * 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: - * Alena Laskavaia - initial API and implementation - *******************************************************************************/ - -package org.eclipse.cdt.codan.checkers.sample; - -import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; -import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarator; -import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; -import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTStatement; -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; - -/** - * @author Alena - * - */ -public class CatchUsesReference extends AbstractIndexAstChecker { - private static final String ER_ID = "org.eclipse.cdt.codan.checkers.sample.CatchUsesReference"; - - public void processAst(IASTTranslationUnit ast) { - // traverse the ast using the visitor pattern. - ast.accept(new OnCatch()); - } - - class OnCatch extends ASTVisitor { - OnCatch() { - shouldVisitStatements = true; - } - public int visit(IASTStatement stmt) { - if (stmt instanceof ICPPASTTryBlockStatement) { - ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt; - ICPPASTCatchHandler[] catchHandlers = tblock.getCatchHandlers(); - for (int i = 0; i < catchHandlers.length; i++) { - ICPPASTCatchHandler catchHandler = catchHandlers[i]; - if (usesReference(catchHandler)) { - reportProblem(ER_ID, catchHandler.getDeclaration(), "Catch clause uses reference in declaration of exception"); - } - } - - return PROCESS_SKIP; - } - return PROCESS_CONTINUE; - } - /** - * @param catchHandler - * @return - */ - private boolean usesReference(ICPPASTCatchHandler catchHandler) { - IASTDeclaration declaration = catchHandler.getDeclaration(); - if (declaration instanceof IASTSimpleDeclaration) { - IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration).getDeclarators(); - for (int i = 0; i < declarators.length; i++) { - IASTDeclarator d = declarators[i]; - IASTPointerOperator[] pointerOperators = d.getPointerOperators(); - for (int j = 0; j < pointerOperators.length; j++) { - IASTPointerOperator po = pointerOperators[j]; - if (po instanceof ICPPASTReferenceOperator) { - return true; - } - - } - } - } - return false; - } - } - - -} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/StatementHasNoEffectChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/StatementHasNoEffectChecker.java deleted file mode 100644 index c08f58a..0000000 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/StatementHasNoEffectChecker.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009 Alena Laskavaia - * 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: - * Alena Laskavaia - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.codan.checkers.sample; - -import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; -import org.eclipse.cdt.core.dom.ast.ASTVisitor; -import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; -import org.eclipse.cdt.core.dom.ast.IASTExpression; -import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; -import org.eclipse.cdt.core.dom.ast.IASTIdExpression; -import org.eclipse.cdt.core.dom.ast.IASTStatement; -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; -import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; -import org.eclipse.cdt.core.dom.ast.IBasicType; -import org.eclipse.cdt.core.dom.ast.IType; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; - -/** - * Checker that detects statements without effect such as - * - * a+b; - * - * or - * - * +b; - * - * - */ -public class StatementHasNoEffectChecker extends AbstractIndexAstChecker { - private static final String ER_ID = "org.eclipse.cdt.codan.checkers.sample.StatementHasNoEffectProblem"; - - public void processAst(IASTTranslationUnit ast) { - // traverse the ast using the visitor pattern. - ast.accept(new CheckStmpVisitor()); - } - - class CheckStmpVisitor extends ASTVisitor { - CheckStmpVisitor() { - shouldVisitStatements = true; - } - - public int visit(IASTStatement stmt) { - if (stmt instanceof IASTExpressionStatement) { - if (hasNoEffect(((IASTExpressionStatement) stmt) - .getExpression())) { - reportProblem(ER_ID, stmt, "Statement has no effect"); - } - return PROCESS_SKIP; - } - return PROCESS_CONTINUE; - } - - /** - * We consider has not effect binary statements without assignment and - * unary statement which is not dec and inc. If operator is overloaded - * we not going to bother. - * - * @param e - * @return - */ - private boolean hasNoEffect(IASTExpression e) { - if (e instanceof IASTBinaryExpression) { - IASTBinaryExpression binExpr = (IASTBinaryExpression) e; - if (binExpr.getOperator() == IASTBinaryExpression.op_assign) - return false; - if (binExpr instanceof CPPASTBinaryExpression) { - // unfortunately ICPPASTBinaryExpression does not have - // getOverload public method - CPPASTBinaryExpression cppBin = (CPPASTBinaryExpression) binExpr; - ICPPFunction overload = cppBin.getOverload(); - if (overload != null) - return false; - IType expressionType = binExpr.getOperand1() - .getExpressionType(); - if (!(expressionType instanceof IBasicType)) { - return false; // must be overloaded but parser could not - // find it - } - } - return true; - } - if (e instanceof IASTUnaryExpression) { - IASTUnaryExpression unaryExpr = (IASTUnaryExpression) e; - int operator = unaryExpr.getOperator(); - switch (operator) { - case IASTUnaryExpression.op_postFixDecr: - case IASTUnaryExpression.op_prefixDecr: - case IASTUnaryExpression.op_postFixIncr: - case IASTUnaryExpression.op_prefixIncr: - return false; - } - return true; - } - if (e instanceof IASTIdExpression) { - // simply a; - return true; - } - return false; - } - } -} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Entries b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Entries new file mode 100644 index 0000000..513604d --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Entries @@ -0,0 +1 @@ +D/checkers//// diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Repository b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Repository index 28a5431..5afb44a 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Repository +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Repository @@ -1 +1 @@ -org.eclipse.cdt/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample +org.eclipse.cdt/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Root b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Root index 04efa23..04efa23 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Root +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Root diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Tag new file mode 100644 index 0000000..3cd1ca4 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Tag @@ -0,0 +1 @@ +TCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Template b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Template index e69de29..e69de29 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/CVS/Template +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/CVS/Template diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/AssignmentInConditionChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/AssignmentInConditionChecker.java index 5ce5661..6a17ef8 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/AssignmentInConditionChecker.java +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/AssignmentInConditionChecker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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 @@ -8,9 +8,9 @@ * Contributors: * Alena Laskavaia - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.codan.checkers.sample; +package org.eclipse.cdt.codan.internal.checkers; -import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; @@ -20,7 +20,7 @@ import org.eclipse.cdt.core.dom.ast.IASTIfStatement; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; public class AssignmentInConditionChecker extends AbstractIndexAstChecker { - private static final String ER_ID = "org.eclipse.cdt.codan.checkers.sample.AssignmentInConditionProblem"; + private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem"; //$NON-NLS-1$ public void processAst(IASTTranslationUnit ast) { // traverse the ast using the visitor pattern. @@ -35,7 +35,7 @@ public class AssignmentInConditionChecker extends AbstractIndexAstChecker { public int visit(IASTExpression expression) { if (isAssignmentExpression(expression) && isUsedAsCondition(expression)) { - reportProblem(ER_ID, expression, "Possible assignment in condition"); + reportProblem(ER_ID, expression, expression.getRawSignature()); } return PROCESS_CONTINUE; } diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Entries b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Entries new file mode 100644 index 0000000..2c93e0c --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Entries @@ -0,0 +1,10 @@ +/AssignmentInConditionChecker.java/1.4/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 +/CatchByReference.java/1.6/Thu Jun 3 17:01:33 2010//TCDT_7_0_0 +/CheckersMessages.java/1.6/Thu May 27 01:21:57 2010//TCDT_7_0_0 +/NamingConventionFunctionChecker.java/1.9/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 +/NonVirtualDestructor.java/1.4/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 +/ReturnChecker.java/1.12/Fri Jun 4 03:03:37 2010//TCDT_7_0_0 +/StatementHasNoEffectChecker.java/1.16/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 +/SuggestedParenthesisChecker.java/1.8/Sun Jun 27 01:30:37 2010//TCDT_7_0_0 +/messages.properties/1.7/Thu Jun 3 17:01:33 2010//TCDT_7_0_0 +D/sample//// diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Repository b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Repository new file mode 100644 index 0000000..7543811 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Repository @@ -0,0 +1 @@ +org.eclipse.cdt/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Root b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Root new file mode 100644 index 0000000..04efa23 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Root @@ -0,0 +1 @@ +:pserver:anonymous@dev.eclipse.org:/cvsroot/tools diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Tag b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Tag new file mode 100644 index 0000000..49a449a --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Tag @@ -0,0 +1 @@ +NCDT_7_0_0 diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Template b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Template new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CVS/Template diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java new file mode 100644 index 0000000..6f0afc8 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CatchByReference.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import org.eclipse.cdt.codan.checkers.CodanCheckersActivator; +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; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTPointer; +import org.eclipse.cdt.core.dom.ast.IASTPointerOperator; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IPointerType; +import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTryBlockStatement; + +/** + * Catching by reference is recommended by C++ experts, for example Herb + * Sutter/Andrei Alexandresscu "C++ Coding Standards", Rule 73 + * "Throw by value, catch by reference". + * For one thing, this avoids copying and potentially slicing the exception. + * + */ +public class CatchByReference extends AbstractIndexAstChecker { + public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.CatchByReference"; //$NON-NLS-1$ + public static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$ + public static final String PARAM_UNKNOWN_TYPE = "unknown"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { + // traverse the ast using the visitor pattern. + ast.accept(new OnCatch()); + } + + class OnCatch extends ASTVisitor { + OnCatch() { + shouldVisitStatements = true; + } + + public int visit(IASTStatement stmt) { + if (stmt instanceof ICPPASTTryBlockStatement) { + try { + ICPPASTTryBlockStatement tblock = (ICPPASTTryBlockStatement) stmt; + ICPPASTCatchHandler[] catchHandlers = tblock + .getCatchHandlers(); + for (int i = 0; i < catchHandlers.length; i++) { + ICPPASTCatchHandler catchHandler = catchHandlers[i]; + IASTDeclaration decl = catchHandler.getDeclaration(); + if (decl instanceof IASTSimpleDeclaration) { + IASTSimpleDeclaration sdecl = (IASTSimpleDeclaration) decl; + IASTDeclSpecifier spec = sdecl.getDeclSpecifier(); + if (!usesReference(catchHandler)) { + if (spec instanceof IASTNamedTypeSpecifier) { + IASTName tname = ((IASTNamedTypeSpecifier) spec) + .getName(); + IType typeName = (IType) tname + .resolveBinding(); + typeName = CxxAstUtils.getInstance() + .unwindTypedef(typeName); + if (typeName instanceof IBasicType + || typeName instanceof IPointerType + || typeName == null) + continue; + if (typeName instanceof IProblemBinding && !shouldReportForUnknownType()) + continue; + String arg = spec.getRawSignature(); + if (!isFilteredArg(arg)) { + reportProblem(ER_ID, decl, arg); + } + } + } + } + } + } catch (Exception e) { + CodanCheckersActivator.log(e); + } + return PROCESS_SKIP; + } + return PROCESS_CONTINUE; + } + + /** + * If it uses reference or ponter + * + * @param catchHandler + * @return + */ + private boolean usesReference(ICPPASTCatchHandler catchHandler) { + IASTDeclaration declaration = catchHandler.getDeclaration(); + if (declaration instanceof IASTSimpleDeclaration) { + IASTDeclarator[] declarators = ((IASTSimpleDeclaration) declaration) + .getDeclarators(); + for (int i = 0; i < declarators.length; i++) { + IASTDeclarator d = declarators[i]; + IASTPointerOperator[] pointerOperators = d + .getPointerOperators(); + for (int j = 0; j < pointerOperators.length; j++) { + IASTPointerOperator po = pointerOperators[j]; + if (po instanceof ICPPASTReferenceOperator) { + return true; + } + if (po instanceof IASTPointer) { + return true; + } + } + } + } + return false; + } + } + + @Override + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + addPreference(problem, PARAM_UNKNOWN_TYPE, + CheckersMessages.CatchByReference_ReportForUnknownType, Boolean.FALSE); + addListPreference(problem, PARAM_EXCEPT_ARG_LIST, + CheckersMessages.GenericParameter_ParameterExceptions, + CheckersMessages.GenericParameter_ParameterExceptionsItem); + } + + public boolean isFilteredArg(String arg) { + Object[] arr = (Object[]) getPreference( + getProblemById(ER_ID, getFile()), PARAM_EXCEPT_ARG_LIST); + for (int i = 0; i < arr.length; i++) { + String str = (String) arr[i]; + if (arg.equals(str)) + return true; + } + return false; + } + + /** + * @return + */ + public boolean shouldReportForUnknownType() { + return (Boolean) getPreference(getProblemById(ER_ID, getFile()), + PARAM_UNKNOWN_TYPE); + } +} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java new file mode 100644 index 0000000..089934f --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import org.eclipse.osgi.util.NLS; + +/** + * Messages + */ +public class CheckersMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.cdt.codan.internal.checkers.messages"; //$NON-NLS-1$ + public static String CatchByReference_ReportForUnknownType; + public static String NamingConventionFunctionChecker_LabelNamePattern; + public static String ReturnChecker_Param0; + public static String GenericParameter_ParameterExceptions; + public static String GenericParameter_ParameterExceptionsItem; + public static String StatementHasNoEffectChecker_ParameterMacro; + public static String SuggestedParenthesisChecker_SuggestParanthesesAroundNot; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, CheckersMessages.class); + } + + private CheckersMessages() { + } +} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java new file mode 100644 index 0000000..4758ed1 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NamingConventionFunctionChecker.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import java.util.regex.Pattern; + +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.core.model.ICheckerWithPreferences; +import org.eclipse.cdt.codan.core.model.IProblem; +import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; + +/** + * This is style checker for function name code style. Pattern parameter is + * regular expression defining the style. + * + */ +public class NamingConventionFunctionChecker extends AbstractIndexAstChecker + implements ICheckerWithPreferences { + private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker"; //$NON-NLS-1$ + public static final String PARAM_KEY = "pattern"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { + final IProblem pt = getProblemById(ER_ID, getFile()); + try { + ast.accept(new ASTVisitor() { + { + shouldVisitDeclarations = true; + } + + public int visit(IASTDeclaration element) { + if (element instanceof IASTFunctionDefinition) { + String parameter = (String) getPreference(pt,PARAM_KEY); + Pattern pattern = Pattern.compile(parameter); + IASTName astName = ((IASTFunctionDefinition) element) + .getDeclarator().getName(); + String name = astName.toString(); + if (!pattern.matcher(name).find()) { + reportProblem(ER_ID, astName, name, parameter); + } + } + return PROCESS_SKIP; + } + }); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.codan.core.model.ICheckerWithPreferences#initParameters + * (org.eclipse.cdt.codan.core.model.IProblemWorkingCopy) + */ + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + addPreference( + problem, + PARAM_KEY, + CheckersMessages.NamingConventionFunctionChecker_LabelNamePattern, + "^[a-z]"); //$NON-NLS-1$ + } + + @Override + public boolean runInEditor() { + return true; + } +} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/NonVirtualDestructor.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NonVirtualDestructor.java index 45f7e72..c4bdbad 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/NonVirtualDestructor.java +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/NonVirtualDestructor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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 @@ -8,12 +8,10 @@ * Contributors: * Alena Laskavaia - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.codan.checkers.sample; +package org.eclipse.cdt.codan.internal.checkers; -import java.text.MessageFormat; - -import org.eclipse.cdt.codan.checkers.Activator; -import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.checkers.CodanCheckersActivator; +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; @@ -33,7 +31,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; * */ public class NonVirtualDestructor extends AbstractIndexAstChecker { - private static final String ER_ID = "org.eclipse.cdt.codan.checkers.sample.NonVirtualDestructorProblem"; + private static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem"; //$NON-NLS-1$ public void processAst(IASTTranslationUnit ast) { // traverse the ast using the visitor pattern. @@ -43,7 +41,7 @@ public class NonVirtualDestructor extends AbstractIndexAstChecker { class OnEachClass extends ASTVisitor { private IASTName className; private IBinding virMethodName; - private IBinding destName; + private IBinding destructorName; OnEachClass() { // shouldVisitDeclarations = true; @@ -55,26 +53,23 @@ public class NonVirtualDestructor extends AbstractIndexAstChecker { try { boolean err = hasErrorCondition(decl); if (err) { - String mess; String clazz = className.toString(); String method = virMethodName.getName(); IASTNode ast = decl; - if (destName != null) { - if (destName instanceof ICPPInternalBinding) { - ICPPInternalBinding bin = (ICPPInternalBinding) destName; - ast = bin.getDeclarations()[0]; + if (destructorName != null) { + if (destructorName instanceof ICPPInternalBinding) { + ICPPInternalBinding bin = (ICPPInternalBinding) destructorName; + IASTNode[] decls = bin.getDeclarations(); + if (decls!=null && decls.length>0) + ast = decls[0]; } - mess = MessageFormat - .format( - "Class ''{0}'' has virtual method ''{1}'' but non-virtual destructor ''{2}''", - clazz, method, destName.getName()); - reportProblem(ER_ID, ast, mess); + reportProblem(ER_ID, ast, clazz, method, destructorName.getName()); } } } catch (DOMException e) { // ignore, no error } catch (Exception e) { - Activator.log(e); + CodanCheckersActivator.log(e); } return PROCESS_SKIP; } @@ -96,7 +91,7 @@ public class NonVirtualDestructor extends AbstractIndexAstChecker { if (binding instanceof ICPPClassType) { ICPPClassType type = (ICPPClassType) binding; virMethodName = null; - destName = null; + destructorName = null; // check for the following conditions: // class has own virtual method and own non-virtual destructor // class has own virtual method and base non-virtual destructor @@ -116,7 +111,7 @@ public class NonVirtualDestructor extends AbstractIndexAstChecker { hasDestructor = true; if (!icppMethod.isVirtual()) { hasOwnNonVirDestructor = true; - destName = icppMethod; + destructorName = icppMethod; } } } @@ -145,8 +140,8 @@ public class NonVirtualDestructor extends AbstractIndexAstChecker { if (icppMethod.isVirtual()) { hasVirDestructor = true; } else { - if (destName == null) - destName = icppMethod; + if (destructorName == null) + destructorName = icppMethod; } } } diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java new file mode 100644 index 0000000..e88c86d --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java @@ -0,0 +1,202 @@ +/******************************************************************************* + * Copyright (c) 2009,2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers; + +import java.util.Iterator; + +import org.eclipse.cdt.codan.core.cxx.model.AbstractAstFunctionChecker; +import org.eclipse.cdt.codan.core.cxx.model.CxxModelsCache; +import org.eclipse.cdt.codan.core.model.IProblem; +import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; +import org.eclipse.cdt.codan.core.model.cfg.ICfgData; +import org.eclipse.cdt.codan.core.model.cfg.IControlFlowGraph; +import org.eclipse.cdt.codan.core.model.cfg.IExitNode; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.c.ICASTSimpleDeclSpecifier; + +/** + * The checker suppose to find issue related to mismatched return value/function + * declaration<br> + * <li>Function declared as returning non-void returns void + * <li>Function declared as returning void has non-void return + * <li>Function declared as returning non-void has no return (requires control + * flow graph) + */ +public class ReturnChecker extends AbstractAstFunctionChecker { + private static final String PARAM_IMPLICIT = "implicit"; //$NON-NLS-1$ + public final String RET_NO_VALUE_ID = "org.eclipse.cdt.codan.checkers.noreturn"; //$NON-NLS-1$ + public final String RET_ERR_VALUE_ID = "org.eclipse.cdt.codan.checkers.errreturnvalue"; //$NON-NLS-1$ + public final String RET_NORET_ID = "org.eclipse.cdt.codan.checkers.errnoreturn"; //$NON-NLS-1$ + + class ReturnStmpVisitor extends ASTVisitor { + private IASTFunctionDefinition func; + boolean hasret; + + ReturnStmpVisitor(IASTFunctionDefinition func) { + shouldVisitStatements = true; + shouldVisitDeclarations = true; + this.func = func; + this.hasret = false; + } + public int visit(IASTDeclaration element) { + if (element!=func) + return PROCESS_SKIP; // skip inner functions + return PROCESS_CONTINUE; + } + public int visit(IASTStatement stmt) { + if (stmt instanceof IASTReturnStatement) { + hasret = true; + IASTReturnStatement ret = (IASTReturnStatement) stmt; + if (!isVoid(func)) { + if (checkImplicitReturn(RET_NO_VALUE_ID) + || isExplicitReturn(func)) { + if (ret.getReturnValue() == null) + reportProblem(RET_NO_VALUE_ID, ret); + } + } else { + if (ret.getReturnValue() != null) { + IType type = ret.getReturnValue().getExpressionType(); + if (isVoid(type)) + return PROCESS_SKIP; + reportProblem(RET_ERR_VALUE_ID, ret.getReturnValue()); + } + } + + return PROCESS_SKIP; + } + return PROCESS_CONTINUE; + } + + } + + /* + * (non-Javadoc) + * + * @see org.eclipse.cdt.codan.core.cxx.model.AbstractAstFunctionChecker# + * processFunction(org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition) + */ + @Override + protected void processFunction(IASTFunctionDefinition func) { + ReturnStmpVisitor visitor = new ReturnStmpVisitor(func); + func.accept(visitor); + if (!visitor.hasret) { + // no return at all + if (!isVoid(func) + && (checkImplicitReturn(RET_NORET_ID) || isExplicitReturn(func))) { + if (endsWithNoExitNode(func)) + reportProblem(RET_NORET_ID, func.getDeclSpecifier()); + } + } + } + + /** + * @param if - problem id + * @return true if need to check inside functions with implicit return + */ + protected boolean checkImplicitReturn(String id) { + final IProblem pt = getProblemById(id, getFile()); + return (Boolean) getPreference(pt,PARAM_IMPLICIT); + } + + /** + * @param func + * @return + */ + protected boolean endsWithNoExitNode(IASTFunctionDefinition func) { + IControlFlowGraph graph = CxxModelsCache.getInstance() + .getControlFlowGraph(func); + Iterator<IExitNode> exitNodeIterator = graph.getExitNodeIterator(); + boolean noexitop = false; + for (; exitNodeIterator.hasNext();) { + IExitNode node = exitNodeIterator.next(); + if (((ICfgData) node).getData() == null) { + // if it real exit node such as return, exit or throw data + // will be an ast node, it is null it is fake node added by the + // graph builder + noexitop = true; + break; + } + } + return noexitop; + } + + /** + * @param func + * @return + */ + protected boolean isExplicitReturn(IASTFunctionDefinition func) { + return getDeclSpecType(func) != ICASTSimpleDeclSpecifier.t_unspecified; + } + + /** + * @param func + * @return + */ + public boolean isVoid(IASTFunctionDefinition func) { + int type = getDeclSpecType(func); + if (type == IASTSimpleDeclSpecifier.t_void) { + IASTFunctionDeclarator declarator = func.getDeclarator(); + if (declarator.getPointerOperators().length == 0) + return true; + } + return false; + } + /** + * check if type if void + * (uses deprecated API for compatibility with 6.0) + * @param type + * @throws DOMException + */ + @SuppressWarnings("deprecation") + public boolean isVoid(IType type) { + if (type instanceof IBasicType) { + try { + if (((IBasicType) type).getType()==IBasicType.t_void) + return true; + } catch (DOMException e) { + return false; + } + } + return false; + } + /** + * @param func + * @return + */ + protected int getDeclSpecType(IASTFunctionDefinition func) { + IASTDeclSpecifier declSpecifier = func.getDeclSpecifier(); + int type = -1; + if (declSpecifier instanceof IASTSimpleDeclSpecifier) { + type = ((IASTSimpleDeclSpecifier) declSpecifier).getType(); + } + return type; + } + + /* checker must implement @link ICheckerWithPreferences */ + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + if (problem.getId().equals(RET_NO_VALUE_ID) + || problem.getId().equals(RET_NORET_ID)) { + addPreference(problem, PARAM_IMPLICIT, + CheckersMessages.ReturnChecker_Param0, Boolean.FALSE); + } + } +} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/StatementHasNoEffectChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/StatementHasNoEffectChecker.java new file mode 100644 index 0000000..331e86b --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/StatementHasNoEffectChecker.java @@ -0,0 +1,196 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 Alena Laskavaia + * 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: + * Alena Laskavaia - initial API and implementation + *******************************************************************************/ +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; +import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; +import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; +import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTBinaryExpression; + +/** + * Checker that detects statements without effect such as + * + * a+b; + * or + * +b; + * + * + */ +public class StatementHasNoEffectChecker extends AbstractIndexAstChecker { + 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 static final String PARAM_EXCEPT_ARG_LIST = "exceptions"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { + ast.accept(new CheckStmpVisitor()); + } + + class CheckStmpVisitor extends ASTVisitor { + CheckStmpVisitor() { + shouldVisitStatements = true; + } + + public int visit(IASTStatement stmt) { + if (stmt instanceof IASTExpressionStatement) { + IASTExpression expression = ((IASTExpressionStatement) stmt) + .getExpression(); + if (hasNoEffect(expression)) { + boolean inMacro = CxxAstUtils.getInstance().isInMacro( + expression); + boolean shouldReportInMacro = shouldReportInMacro(); + if (inMacro && !shouldReportInMacro) + return PROCESS_SKIP; + String arg = expression.getRawSignature(); + if (!isFilteredArg(arg)) + reportProblem(ER_ID, stmt, arg); + } + return PROCESS_SKIP; + } + return PROCESS_CONTINUE; + } + + /** + * We consider has not effect binary statements without assignment and + * unary statement which is not dec and inc. If operator is overloaded + * we not going to bother. + * + * @param e + * @return + */ + private boolean hasNoEffect(IASTExpression e) { + if (e instanceof IASTBinaryExpression) { + IASTBinaryExpression binExpr = (IASTBinaryExpression) e; + if (isPossibleAssignment(binExpr)) + return false; + switch (binExpr.getOperator()) { + case IASTBinaryExpression.op_logicalOr: + case IASTBinaryExpression.op_logicalAnd: + return hasNoEffect(binExpr.getOperand1()) + && hasNoEffect(binExpr.getOperand2()); + } + return true; + } + if (e instanceof IASTUnaryExpression) { + IASTUnaryExpression unaryExpr = (IASTUnaryExpression) e; + int operator = unaryExpr.getOperator(); + switch (operator) { + case IASTUnaryExpression.op_postFixDecr: + case IASTUnaryExpression.op_prefixDecr: + case IASTUnaryExpression.op_postFixIncr: + case IASTUnaryExpression.op_prefixIncr: + case IASTUnaryExpression.op_throw: + return false; + case IASTUnaryExpression.op_bracketedPrimary: + return hasNoEffect(unaryExpr.getOperand()); + } + return true; + } + // simply a; + if (e instanceof IASTIdExpression) { + // check if it is part of GNU comp stmt expression i.e. ({foo();a;}) + IASTNode parent = e.getParent(); + if (parent instanceof IASTExpressionStatement) { + IASTNode parent2 = parent.getParent(); + if (parent2 instanceof IASTCompoundStatement) { + IASTNode parent3 = parent2.getParent(); + if (parent3 instanceof IGNUASTCompoundStatementExpression) { + return false; + } + } + } + return true; + } + return false; + } + } + + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + addPreference(problem, PARAM_MACRO_ID, + CheckersMessages.StatementHasNoEffectChecker_ParameterMacro, + Boolean.TRUE); + addListPreference( + problem, + PARAM_EXCEPT_ARG_LIST, + CheckersMessages.GenericParameter_ParameterExceptions, + CheckersMessages.GenericParameter_ParameterExceptionsItem); + } + + /**s + * @param paramExceptArgList + * @param arg + * @return + */ + public boolean isFilteredArg(String arg) { + Object[] arr = (Object[]) getPreference( + getProblemById(ER_ID, getFile()), PARAM_EXCEPT_ARG_LIST); + for (int i = 0; i < arr.length; i++) { + String str = (String) arr[i]; + if (arg.equals(str)) + return true; + } + return false; + } + + /** + * @return + */ + public boolean shouldReportInMacro() { + return (Boolean) getPreference(getProblemById(ER_ID, getFile()), + PARAM_MACRO_ID); + } + + @SuppressWarnings("restriction") + public boolean isPossibleAssignment(IASTBinaryExpression expr) { + switch (expr.getOperator()) { + case IASTBinaryExpression.op_assign: + case IASTBinaryExpression.op_binaryAndAssign: + case IASTBinaryExpression.op_binaryOrAssign: + case IASTBinaryExpression.op_binaryXorAssign: + case IASTBinaryExpression.op_divideAssign: + case IASTBinaryExpression.op_minusAssign: + case IASTBinaryExpression.op_moduloAssign: + case IASTBinaryExpression.op_multiplyAssign: + case IASTBinaryExpression.op_plusAssign: + case IASTBinaryExpression.op_shiftLeftAssign: + case IASTBinaryExpression.op_shiftRightAssign: + return true; + } + if (expr instanceof CPPASTBinaryExpression) { + // unfortunately ICPPASTBinaryExpression does not have + // getOverload public method + CPPASTBinaryExpression cppBin = (CPPASTBinaryExpression) expr; + ICPPFunction overload = cppBin.getOverload(); + if (overload != null) + return true; + IType expressionType = cppBin.getOperand1().getExpressionType(); + if (!(expressionType instanceof IBasicType)) { + return true; // must be overloaded but parser could not + // find it + } + } + return false; + } +} diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/SuggestedParenthesisChecker.java b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuggestedParenthesisChecker.java index 27712b4..659703d 100644 --- a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/checkers/sample/SuggestedParenthesisChecker.java +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/SuggestedParenthesisChecker.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009 Alena Laskavaia + * Copyright (c) 2009, 2010 Alena Laskavaia * 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 @@ -8,20 +8,21 @@ * Contributors: * Alena Laskavaia - initial API and implementation *******************************************************************************/ -package org.eclipse.cdt.codan.checkers.sample; +package org.eclipse.cdt.codan.internal.checkers; -import org.eclipse.cdt.codan.core.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.core.cxx.model.AbstractIndexAstChecker; +import org.eclipse.cdt.codan.core.model.IProblemWorkingCopy; import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression; -import org.eclipse.cdt.core.dom.ast.IASTForStatement; -import org.eclipse.cdt.core.dom.ast.IASTIfStatement; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; /** - * This checker finds a problems that cause by lack of understanding operator + * This checker finds a problems which are caused by lack of understanding + * operator * precedence in C. In any case it is better to surround expressions in * parenthesis to improve readability. Example: ! x>0 && x<10 (this would be * (!x)>0 && x<10 in C) We only look for &&, || and ! operators (and binary | & @@ -31,7 +32,10 @@ import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; * */ public class SuggestedParenthesisChecker extends AbstractIndexAstChecker { - private static final String ER_ID = "org.eclipse.cdt.codan.checkers.sample.SuggestedParenthesisProblem"; + public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem"; //$NON-NLS-1$ + public static final String PARAM_NOT = "paramNot"; //$NON-NLS-1$ + + public void processAst(IASTTranslationUnit ast) { // traverse the ast using the visitor pattern. @@ -39,32 +43,27 @@ public class SuggestedParenthesisChecker extends AbstractIndexAstChecker { } class ExpressionVisitor extends ASTVisitor { - private SuspiciousExpressionVisitor svis; - ExpressionVisitor() { shouldVisitExpressions = true; - svis = new SuspiciousExpressionVisitor(); } public int visit(IASTExpression expression) { int precedence = getPrecedence(expression); - if (precedence == 2) { // unary not - if (isUsedAsOperand(expression)) { - reportProblem(ER_ID, expression, - "Suggested parenthesis around expression"); - return PROCESS_SKIP; - } - } - if (precedence >= 0) { - synchronized (svis) { // since we use only one instance of this - // visitor sync just in case - svis.init(expression); - expression.accept(svis); - if (svis.suspicious == true) { - reportProblem(ER_ID, svis.other, - "Suggested parenthesis around expression"); + IASTNode parent = expression.getParent(); + if (parent instanceof IASTExpression) { + IASTExpression parentExpr = (IASTExpression) parent; + if (isInParentesis(expression)) + return PROCESS_CONTINUE; + if (precedence == 2) { // unary not + if (isParamNot() && isUsedAsOperand(expression)) { + reportProblem(ER_ID, expression, expression.getRawSignature()); return PROCESS_SKIP; } + } else if (precedence >= 0) { + int pp = getPrecedence(parentExpr); + if (pp == -1 || pp == precedence) + return PROCESS_CONTINUE; + reportProblem(ER_ID, expression, expression.getRawSignature()); } } return PROCESS_CONTINUE; @@ -73,7 +72,7 @@ public class SuggestedParenthesisChecker extends AbstractIndexAstChecker { private boolean isUsedAsOperand(IASTExpression expression) { ASTNodeProperty prop = expression.getPropertyInParent(); if (prop == IASTBinaryExpression.OPERAND_ONE - || prop == IASTBinaryExpression.OPERAND_TWO + // || prop == IASTBinaryExpression.OPERAND_TWO || prop == IASTUnaryExpression.OPERAND) return true; return false; @@ -106,38 +105,37 @@ public class SuggestedParenthesisChecker extends AbstractIndexAstChecker { return -1; } - class SuspiciousExpressionVisitor extends ASTVisitor { - IASTExpression parent; - IASTExpression other; - boolean suspicious = false; - - void init(IASTExpression e) { - parent = e; - suspicious = false; + /** + * @param parent + * @return + */ + private boolean isInParentesis(IASTExpression node) { + IASTNode parent = node.getParent(); + if (parent instanceof IASTUnaryExpression) { + IASTUnaryExpression br = (IASTUnaryExpression) parent; + if (br.getOperator() == IASTUnaryExpression.op_bracketedPrimary) { + return true; + } } + return false; + } - SuspiciousExpressionVisitor() { - shouldVisitExpressions = true; - } + public boolean isParamNot() { + return (Boolean) getPreference(getProblemById(ER_ID, getFile()), + PARAM_NOT); + } - public int visit(IASTExpression expression) { - if (expression == parent) - return PROCESS_CONTINUE; - if (expression instanceof IASTUnaryExpression) { - IASTUnaryExpression uExpr = (IASTUnaryExpression) expression; - int operator = uExpr.getOperator(); - if (operator == IASTUnaryExpression.op_bracketedPrimary) { - return PROCESS_SKIP; - } - } - if (getPrecedence(expression) < 0) // not considered operator - return PROCESS_CONTINUE; - if (getPrecedence(expression) == getPrecedence(parent)) { - return PROCESS_SKIP; - } - suspicious = true; - other = expression; - return PROCESS_ABORT; - } + /* + * (non-Javadoc) + * + * @see + * org.eclipse.cdt.codan.core.model.AbstractCheckerWithProblemPreferences + * #initPreferences(org.eclipse.cdt.codan.core.model.IProblemWorkingCopy) + */ + @Override + public void initPreferences(IProblemWorkingCopy problem) { + super.initPreferences(problem); + addPreference(problem, PARAM_NOT, + CheckersMessages.SuggestedParenthesisChecker_SuggestParanthesesAroundNot, Boolean.FALSE); } } diff --git a/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties new file mode 100644 index 0000000..94c7757 --- /dev/null +++ b/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/messages.properties @@ -0,0 +1,17 @@ +############################################################################### +# Copyright (c) 2010 Alena Laskavaia 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: +# Alena Laskavaia - initial API and implementation +############################################################################### +CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved +NamingConventionFunctionChecker_LabelNamePattern=Name Pattern +ReturnChecker_Param0=Also check functions with implicit return value +GenericParameter_ParameterExceptions=Exceptions (value of the problem argument) +GenericParameter_ParameterExceptionsItem=Value of the argument +StatementHasNoEffectChecker_ParameterMacro=Report problem in statements that comes from macro expansion +SuggestedParenthesisChecker_SuggestParanthesesAroundNot=Suggest parentesis around not operator |