mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 17:56:01 +02:00
Bug 311268 added checker to check for return values
This commit is contained in:
parent
b19600d913
commit
dab4cc2c7e
3 changed files with 203 additions and 0 deletions
|
@ -83,5 +83,40 @@
|
||||||
name="Name convention for function">
|
name="Name convention for function">
|
||||||
</problem>
|
</problem>
|
||||||
</checker>
|
</checker>
|
||||||
|
<checker
|
||||||
|
class="org.eclipse.cdt.codan.internal.checkers.ReturnChecker"
|
||||||
|
id="org.eclipse.cdt.codan.internal.checkers.ReturnChecker"
|
||||||
|
name="Return inconsistencies">
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
|
||||||
|
defaultEnabled="true"
|
||||||
|
defaultSeverity="Error"
|
||||||
|
description="Return statment has no return value, if somebody would use return value from this function it would be random"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.noreturn"
|
||||||
|
messagePattern="Return without value, in function returning non-void"
|
||||||
|
name="No return value">
|
||||||
|
</problem>
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
|
||||||
|
defaultEnabled="true"
|
||||||
|
defaultSeverity="Error"
|
||||||
|
description="Return statement has a value, but function is declared to return void. Did you mean to declare function with return value?"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.errreturnvalue"
|
||||||
|
messagePattern="Return has value, in function returning void"
|
||||||
|
name="Unused return value">
|
||||||
|
</problem>
|
||||||
|
<problem
|
||||||
|
category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
|
||||||
|
defaultEnabled="true"
|
||||||
|
defaultSeverity="Warning"
|
||||||
|
description="No return statement in a function which is declared to return value"
|
||||||
|
id="org.eclipse.cdt.codan.checkers.errnoreturn"
|
||||||
|
messagePattern="No return, in function returning non-void"
|
||||||
|
name="No return">
|
||||||
|
</problem>
|
||||||
|
</checker>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</extension>
|
</extension>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
|
@ -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<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 {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue