diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml index 7566fc5f114..b80a55cbff7 100644 --- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml +++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml @@ -83,5 +83,40 @@ name="Name convention for function"> + + + + + + + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java new file mode 100644 index 00000000000..ef275b35401 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ReturnChecker.java @@ -0,0 +1,110 @@ +/******************************************************************************* + * 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.model.AbstractAstFunctionChecker; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +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.c.ICASTSimpleDeclSpecifier; + +/** + * The checker suppose to find issue related to mismatched return value/function + * declaration
+ *
  • Function declared as returning non-void returns void + *
  • Function declared as returning void has non-void return + *
  • Function declared as returning non-void has no return (requires control + * flow graph) + */ +public class ReturnChecker extends AbstractAstFunctionChecker { + 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; + this.func = func; + this.hasret = false; + } + + public int visit(IASTStatement stmt) { + if (stmt instanceof IASTReturnStatement) { + IASTReturnStatement ret = (IASTReturnStatement) stmt; + if (!isVoid(func)) { + if (getDeclSpecType(func) != ICASTSimpleDeclSpecifier.t_unspecified) { + if (ret.getReturnValue() == null) + reportProblem(RET_NO_VALUE_ID, ret); + } + } else { + if (ret.getReturnValue() != null) + reportProblem(RET_ERR_VALUE_ID, ret.getReturnValue()); + } + hasret = true; + 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) + && getDeclSpecType(func) != ICASTSimpleDeclSpecifier.t_unspecified) { + reportProblem(RET_NORET_ID, func.getDeclSpecifier()); + } + } + } + + /** + * @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; + } + + /** + * @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; + } +} diff --git a/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractAstFunctionChecker.java b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractAstFunctionChecker.java new file mode 100644 index 00000000000..fbc9c550fe7 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.cxx/src/org/eclipse/cdt/codan/core/cxx/model/AbstractAstFunctionChecker.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.core.cxx.model; + +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.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; + +/** + * Abstract class for checkers that do all the work on function definition level + */ +public abstract class AbstractAstFunctionChecker extends + AbstractIndexAstChecker { + public void processAst(IASTTranslationUnit ast) { + // traverse the ast using the visitor pattern. + ast.accept(new ASTVisitor() { + { + shouldVisitDeclarations = true; + } + + public int visit(IASTDeclaration element) { + if (element instanceof IASTFunctionDefinition) { + processFunction((IASTFunctionDefinition) element); + return PROCESS_CONTINUE; // this is to support gcc extension + // for enclosed functions + } + if (element instanceof IASTSimpleDeclaration) { + IASTDeclSpecifier declSpecifier = ((IASTSimpleDeclaration) element) + .getDeclSpecifier(); + if (declSpecifier instanceof ICPPASTCompositeTypeSpecifier) { + return PROCESS_CONTINUE; // c++ methods + } + } + return PROCESS_SKIP; + } + }); + } + + /** + * Process function. + * + * @param func + * - ast node representing function definition + */ + protected abstract void processFunction(IASTFunctionDefinition func); +}