mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-19 06:55:23 +02:00
Bug 339795 - [checker] Checker that finds class members that are not
initialized in constructor
This commit is contained in:
parent
82a3d0c280
commit
3b6f6642b8
7 changed files with 727 additions and 3 deletions
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2010 Alena Laskavaia and others.
|
||||
# Copyright (c) 2010, 2011 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
|
||||
|
@ -111,6 +111,10 @@ checker.name.AbstractClassCreation = Abstract class cannot be instantiated
|
|||
problem.name.AbstractClassCreation = Abstract class cannot be instantiated
|
||||
problem.messagePattern.AbstractClassCreation = The type ''{0}'' must implement the inherited pure virtual method ''{1}''
|
||||
problem.description.AbstractClassCreation = All inherited pure virtual methods must be implemented to allow instantiation of the class
|
||||
checker.name.ClassMembersInitialization = Class members should be properly initialized
|
||||
problem.name.ClassMembersInitialization = Class members should be properly initialized
|
||||
problem.messagePattern.ClassMembersInitialization = Member ''{0}'' was not initialized in this constructor
|
||||
problem.description.ClassMembersInitialization = Class members should be properly initialized to avoid random behavior
|
||||
|
||||
checker.name.UnusedSymbolInFileScopeChecker = Unused symbols and declarations in file scope
|
||||
problem.description.UnusedVariableDeclarationProblem = Finds unused global variable declarations in file scope
|
||||
|
|
|
@ -384,5 +384,19 @@
|
|||
name="%problem.name.UnusedStaticFunctionProblem">
|
||||
</problem>
|
||||
</checker>
|
||||
<checker
|
||||
class="org.eclipse.cdt.codan.internal.checkers.ClassMembersInitializationChecker"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization"
|
||||
name="%checker.name.ClassMembersInitialization">
|
||||
<problem
|
||||
category="org.eclipse.cdt.codan.core.categories.ProgrammingProblems"
|
||||
defaultEnabled="true"
|
||||
defaultSeverity="Warning"
|
||||
description="%problem.description.ClassMembersInitialization"
|
||||
id="org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization"
|
||||
messagePattern="%problem.messagePattern.ClassMembersInitialization"
|
||||
name="%problem.name.ClassMembersInitialization">
|
||||
</problem>
|
||||
</checker>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009,2010 Alena Laskavaia
|
||||
* Copyright (c) 2009, 2011 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
|
||||
|
@ -20,6 +20,7 @@ public class CheckersMessages extends NLS {
|
|||
public static String CaseBreakChecker_EmptyCaseDescription;
|
||||
public static String CaseBreakChecker_LastCaseDescription;
|
||||
public static String CatchByReference_ReportForUnknownType;
|
||||
public static String ClassMembersInitializationChecker_SkipConstructorsWithFCalls;
|
||||
public static String NamingConventionFunctionChecker_LabelNamePattern;
|
||||
public static String NamingConventionFunctionChecker_ParameterMethods;
|
||||
public static String ReturnChecker_Param0;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2010 Alena Laskavaia and others.
|
||||
# Copyright (c) 2010, 2011 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
|
||||
|
@ -11,6 +11,7 @@
|
|||
CaseBreakChecker_DefaultNoBreakCommentDescription=Comment text to suppress the problem (regular expression):
|
||||
CaseBreakChecker_EmptyCaseDescription=Check also empty case statement (except if last)
|
||||
CaseBreakChecker_LastCaseDescription=Check also the last case statement
|
||||
ClassMembersInitializationChecker_SkipConstructorsWithFCalls=Skip constructors with initialization function calls
|
||||
CatchByReference_ReportForUnknownType=Report a problem if type cannot be resolved
|
||||
NamingConventionFunctionChecker_LabelNamePattern=Name Pattern
|
||||
NamingConventionFunctionChecker_ParameterMethods=Also check C++ method names
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Anton Gorenkov
|
||||
* 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:
|
||||
* Anton Gorenkov - initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.internal.checkers;
|
||||
|
||||
import java.util.Stack;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
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.IASTDeclaration;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||
import org.eclipse.cdt.core.dom.ast.IEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.IField;
|
||||
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVariableReadWriteFlags;
|
||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
|
||||
|
||||
/**
|
||||
* Checks that class members of simple types (int, float, pointers,
|
||||
* enumeration types, ...) are properly initialized in constructor.
|
||||
* Not initialized members may cause to unstable or random behavior
|
||||
* of methods that are working with their value.
|
||||
*
|
||||
* @author Anton Gorenkov
|
||||
*
|
||||
*/
|
||||
public class ClassMembersInitializationChecker extends AbstractIndexAstChecker {
|
||||
public static final String ER_ID = "org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization"; //$NON-NLS-1$
|
||||
public static final String PARAM_SKIP = "skip"; //$NON-NLS-1$
|
||||
|
||||
public void processAst(IASTTranslationUnit ast) {
|
||||
ast.accept(new OnEachClass());
|
||||
}
|
||||
|
||||
class OnEachClass extends ASTVisitor {
|
||||
|
||||
// NOTE: Classes can be nested and even can be declared in constructors of the other classes
|
||||
private Stack< Set<IField> > constructorsStack = new Stack< Set<IField> >();
|
||||
|
||||
OnEachClass() {
|
||||
shouldVisitDeclarations = true;
|
||||
shouldVisitNames = true;
|
||||
shouldVisitExpressions = skipConstructorsWithFCalls();
|
||||
}
|
||||
|
||||
public int visit(IASTDeclaration declaration) {
|
||||
ICPPConstructor constructor = getConstructor(declaration);
|
||||
if (constructor != null) {
|
||||
Set<IField> fieldsInConstructor = constructorsStack.push(new HashSet<IField>());
|
||||
|
||||
// Add all class fields
|
||||
for (IField field : constructor.getClassOwner().getDeclaredFields()) {
|
||||
if (isSimpleType(field.getType()) && !field.isStatic()) {
|
||||
fieldsInConstructor.add(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
public int leave(IASTDeclaration declaration) {
|
||||
if (getConstructor(declaration) != null) {
|
||||
for (IField field : constructorsStack.pop()) {
|
||||
reportProblem(ER_ID, declaration, field.getName());
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
public int visit(IASTExpression expression) {
|
||||
if (!constructorsStack.empty() && expression instanceof IASTFunctionCallExpression) {
|
||||
Set<IField> actualContructorFields = constructorsStack.peek();
|
||||
if (!actualContructorFields.isEmpty()) {
|
||||
boolean skipCurrentConstructor = false;
|
||||
IASTFunctionCallExpression fCall = (IASTFunctionCallExpression)expression;
|
||||
IASTExpression fNameExp = fCall.getFunctionNameExpression();
|
||||
if (fNameExp instanceof IASTIdExpression) {
|
||||
IASTIdExpression fName = (IASTIdExpression)fNameExp;
|
||||
IBinding fBinding = fName.getName().resolveBinding();
|
||||
if (fBinding instanceof ICPPMethod) {
|
||||
ICPPMethod method = (ICPPMethod)fBinding;
|
||||
ICompositeType constructorOwner = actualContructorFields.iterator().next().getCompositeTypeOwner();
|
||||
if (constructorOwner == method.getClassOwner() && !method.getType().isConst()) {
|
||||
skipCurrentConstructor = true;
|
||||
}
|
||||
} else if (fBinding instanceof ICPPFunction) {
|
||||
for (IASTInitializerClause argument : fCall.getArguments()) {
|
||||
if (referencesThis(argument)) {
|
||||
skipCurrentConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (skipCurrentConstructor) {
|
||||
constructorsStack.peek().clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
/** Checks whether expression references this (directly, by pointer or by reference)
|
||||
*
|
||||
*/
|
||||
public boolean referencesThis(IASTNode expr) {
|
||||
if (expr instanceof IASTLiteralExpression) {
|
||||
IASTLiteralExpression litArg = (IASTLiteralExpression)expr;
|
||||
if (litArg.getKind() == IASTLiteralExpression.lk_this) {
|
||||
return true;
|
||||
}
|
||||
} else if (expr instanceof ICPPASTUnaryExpression) {
|
||||
ICPPASTUnaryExpression unExpr = (ICPPASTUnaryExpression)expr;
|
||||
switch (unExpr.getOperator()) {
|
||||
case ICPPASTUnaryExpression.op_amper:
|
||||
case ICPPASTUnaryExpression.op_star:
|
||||
case ICPPASTUnaryExpression.op_bracketedPrimary:
|
||||
return referencesThis(unExpr.getOperand());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int visit(IASTName name) {
|
||||
if (!constructorsStack.empty()) {
|
||||
Set<IField> actualContructorFields = constructorsStack.peek();
|
||||
if (!actualContructorFields.isEmpty()) {
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (actualContructorFields.contains(binding)) {
|
||||
if ((CPPVariableReadWriteFlags.getReadWriteFlags(name) & PDOMName.WRITE_ACCESS) != 0) {
|
||||
actualContructorFields.remove(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
/** Checks whether class member of the specified type should be initialized
|
||||
*
|
||||
* @param type Type to check
|
||||
* @return true if type is:
|
||||
* - basic type (int, float, ...)
|
||||
* - pointer
|
||||
* - enum
|
||||
* - reference (should be initialized in initialization list)
|
||||
* - typedef to the another native type.
|
||||
*
|
||||
* @note: Not supported types (but maybe should be):
|
||||
* - array
|
||||
* - union
|
||||
* - unknown type (need user preference?)
|
||||
* - template parameter (need user preference?)
|
||||
*/
|
||||
private boolean isSimpleType(IType type) {
|
||||
return (type instanceof IBasicType ||
|
||||
type instanceof IPointerType ||
|
||||
type instanceof IEnumeration ||
|
||||
type instanceof ICPPReferenceType ||
|
||||
(type instanceof ITypedef && isSimpleType( ((ITypedef)type).getType()) ) );
|
||||
}
|
||||
|
||||
/** Checks that specified declaration is a class constructor
|
||||
* (it is a class member and its name is equal to class name)
|
||||
*/
|
||||
private ICPPConstructor getConstructor(IASTDeclaration decl) {
|
||||
if (decl instanceof ICPPASTFunctionDefinition) {
|
||||
ICPPASTFunctionDefinition functionDefinition = (ICPPASTFunctionDefinition)decl;
|
||||
IBinding binding = functionDefinition.getDeclarator().getName().resolveBinding();
|
||||
if (binding instanceof ICPPConstructor) {
|
||||
ICPPConstructor constructor = (ICPPConstructor) binding;
|
||||
if (constructor.getClassOwner().getKey()!=ICPPClassType.k_union) {
|
||||
return constructor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initPreferences(IProblemWorkingCopy problem) {
|
||||
super.initPreferences(problem);
|
||||
addPreference(problem, PARAM_SKIP, CheckersMessages.ClassMembersInitializationChecker_SkipConstructorsWithFCalls, Boolean.TRUE);
|
||||
}
|
||||
|
||||
public boolean skipConstructorsWithFCalls() {
|
||||
return (Boolean) getPreference(getProblemById(ER_ID, getFile()), PARAM_SKIP);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,480 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2011 Anton Gorenkov
|
||||
* 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:
|
||||
* Anton Gorenkov - initial implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.codan.core.internal.checkers;
|
||||
|
||||
import org.eclipse.cdt.codan.core.test.CheckerTestCase;
|
||||
import org.eclipse.cdt.codan.internal.checkers.ClassMembersInitializationChecker;
|
||||
|
||||
/**
|
||||
* Test for {@see ClassMembersInitializationChecker} class
|
||||
*
|
||||
*/
|
||||
public class ClassMembersInitializationCheckerTest extends CheckerTestCase {
|
||||
@Override
|
||||
public boolean isCpp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
enableProblems(ClassMembersInitializationChecker.ER_ID);
|
||||
}
|
||||
|
||||
private void disableSkipConstructorsWithFCalls() {
|
||||
setPreferenceValue(ClassMembersInitializationChecker.ER_ID, ClassMembersInitializationChecker.PARAM_SKIP, false);
|
||||
}
|
||||
|
||||
public void checkMultiErrorsOnLine(int line, int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
checkErrorLine(line);
|
||||
}
|
||||
assertEquals(count, markers.length);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// int m;
|
||||
// C() : m(0) {} // No warnings.
|
||||
// };
|
||||
public void testInitializationListShouldBeChecked() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// int m;
|
||||
// C() { m = 0; } // No warnings.
|
||||
// };
|
||||
public void testAssignmentsInContructorShouldBeChecked() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// int m;
|
||||
// unsigned int ui;
|
||||
// float f;
|
||||
// double d;
|
||||
// bool b;
|
||||
// char c;
|
||||
// long l;
|
||||
// C() {} // 7 warnings for: m, ui, f, d, b, c, l.
|
||||
// };
|
||||
public void testBasicTypesShouldBeInitialized() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkMultiErrorsOnLine(9, 7);
|
||||
}
|
||||
|
||||
// class Value {};
|
||||
// class C {
|
||||
// int* i;
|
||||
// Value* v;
|
||||
// C() {} // 2 warnings for: i, v.
|
||||
// }
|
||||
public void testPointersShouldBeInitialized() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkMultiErrorsOnLine(5, 2);
|
||||
}
|
||||
|
||||
// class Value {};
|
||||
// class C {
|
||||
// int& i;
|
||||
// Value& v;
|
||||
// C() {} // 2 warnings for: i, v.
|
||||
// }
|
||||
public void testReferencesShouldBeInitialized() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkMultiErrorsOnLine(5, 2);
|
||||
}
|
||||
|
||||
// enum Enum { v1, v2 };
|
||||
// class C {
|
||||
// Enum e;
|
||||
// C() {} // 1 warning for: e.
|
||||
// }
|
||||
public void testEnumsShouldBeInitialized() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkMultiErrorsOnLine(4, 1);
|
||||
}
|
||||
|
||||
// enum Enum { v1, v2 };
|
||||
// class Value {};
|
||||
// typedef int IntTypedef;
|
||||
// typedef int* IntPtrTypedef;
|
||||
// typedef int& IntRefTypedef;
|
||||
// typedef Enum EnumTypedef;
|
||||
// typedef Value ValueTypedef;
|
||||
// class C {
|
||||
// IntTypedef i;
|
||||
// IntPtrTypedef ip;
|
||||
// IntRefTypedef ir;
|
||||
// EnumTypedef e;
|
||||
// ValueTypedef v;
|
||||
// C() {} // 5 warnings for: i, ip, ir, e.
|
||||
// }
|
||||
public void testTypedefsShouldBeInitialized() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkMultiErrorsOnLine(14, 4);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() : i1(0) {} // 1 warning for: i2.
|
||||
// C(int) : i2(0) {} // 1 warning for: i1.
|
||||
// int i1, i2;
|
||||
// };
|
||||
public void testAFewConstructorsHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(2, 3);
|
||||
}
|
||||
|
||||
// template <typename T1, typename T2>
|
||||
// class C {
|
||||
// C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
||||
// int i1, i2;
|
||||
// T1 t1;
|
||||
// T2 t2;
|
||||
// };
|
||||
public void testTemplateClassHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// template <typename T>
|
||||
// C() : i1(0) {} // 1 warning for: i2.
|
||||
// int i1, i2;
|
||||
// };
|
||||
public void testTemplateConstructorHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C(); // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
public void testTemplateConstructorDeclarationOnlyHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C();
|
||||
// int i1, i2;
|
||||
// };
|
||||
// C::C() : i1(0) {} // 1 warning for: i2.
|
||||
public void testExternalContructorHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(5);
|
||||
}
|
||||
|
||||
// template <typename T1, typename T2>
|
||||
// class C {
|
||||
// C();
|
||||
// int i1, i2;
|
||||
// T1 t1;
|
||||
// T2 t2;
|
||||
// };
|
||||
// C::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
||||
public void testExternalContructorOfTemplateClassHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(8);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// template <typename T>
|
||||
// C();
|
||||
// int i1, i2;
|
||||
// };
|
||||
// template <typename T>
|
||||
// C::C() : i1(0) {} // 1 warning for: i2.
|
||||
public void testExternalTemplateContructorHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(7);
|
||||
}
|
||||
|
||||
// template <typename T1, typename T2>
|
||||
// class C {
|
||||
// template <typename T>
|
||||
// C();
|
||||
// int i1, i2;
|
||||
// T1 t1;
|
||||
// T2 t2;
|
||||
// };
|
||||
// template <typename T1, typename T2>
|
||||
// template <typename T>
|
||||
// C<T1,T2>::C() : i1(0), t1(T1()) {} // 1 warning for: i2.
|
||||
public void testExternalTemplateContructorOfTemplateClassHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(11);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// class NestedC {
|
||||
// NestedC() : i(0) {} // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
// C() {} // 1 warning for: i.
|
||||
// int i;
|
||||
// };
|
||||
public void testNestedClassesHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(6);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() // 1 warning for: i.
|
||||
// {
|
||||
// class NestedC {
|
||||
// NestedC() { i = 0; } // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
// }
|
||||
// int i;
|
||||
// };
|
||||
public void testNestedClassInConstructorHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(2);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C();
|
||||
// int i;
|
||||
// };
|
||||
//
|
||||
// C::C() // 1 warning for: i.
|
||||
// {
|
||||
// class NestedC { // No warnings.
|
||||
// NestedC() { i = 0; }
|
||||
// int i;
|
||||
// };
|
||||
// }
|
||||
public void testNestedClassInExternalConstructorHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(6);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() // 1 warning for: i.
|
||||
// {
|
||||
// class NestedC {
|
||||
// NestedC() { i = 0; } // No warnings.
|
||||
// void C() { i = 0; } // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
// }
|
||||
// int i;
|
||||
// };
|
||||
public void testNestedClassWithMethodNamedAsAnotherClassHandling() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(2);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() {} // 1 warning for: i.
|
||||
// int someFunction() { i = 0; } // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
public void testAssignmentIsNotInConstructor() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(2);
|
||||
}
|
||||
|
||||
// class CBase {
|
||||
// CBase() : i1(0) {} // No warnings.
|
||||
// int i1;
|
||||
// };
|
||||
// class CDerived : public CBase {
|
||||
// CDerived() : i2(0) {} // No warnings.
|
||||
// int i2;
|
||||
// };
|
||||
public void testBaseClassMemberShouldNotBeTakenIntoAccount() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() {} // No warnings.
|
||||
// static int i1, i2;
|
||||
// };
|
||||
// int C::i1 = 0;
|
||||
// // NOTE: Static members are always initialized with 0, so there should not be warning on C::i2
|
||||
// int C::i2;
|
||||
public void testNoErrorsOnStaticMembers() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void func(int & a) { a = 0; }
|
||||
// class C {
|
||||
// C() { func(i); } // No warnings.
|
||||
// int i;
|
||||
// };
|
||||
public void testNoErrorsOnFunctionCallInitialization() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// void func(const int & a) {}
|
||||
// class C {
|
||||
// C() { func(i); } // 1 warning for: i.
|
||||
// int i;
|
||||
// };
|
||||
public void testNoErrorsOnReadingFunctionCall() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3);
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() { (i1) = 0; *&i2 = 0; } // No warnings.
|
||||
// int i1, i2;
|
||||
// };
|
||||
public void testNoErrorsOnComplexAssignment() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// C() : i1(0) { // No warnings.
|
||||
// i2 = i1;
|
||||
// int someVar = 0;
|
||||
// i3 = someVar;
|
||||
// }
|
||||
// int i1, i2, i3;
|
||||
// };
|
||||
public void testNoErrorsOnChainInitialization() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class A { protected: A(){} public: int a; }; // 1 warning for: a.
|
||||
// class C: public A {
|
||||
// C() {
|
||||
// a = 1;
|
||||
// }
|
||||
// };
|
||||
public void testErrorOnProtectedConstructor() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(1);
|
||||
}
|
||||
|
||||
// struct S {
|
||||
// int i;
|
||||
// S() {} // 1 warning for: i.
|
||||
// };
|
||||
public void testCheckStructs() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3);
|
||||
}
|
||||
|
||||
// union U {
|
||||
// int a;
|
||||
// char b;
|
||||
// U() { // No warnings.
|
||||
// a=0;
|
||||
// }
|
||||
// };
|
||||
public void testSkipUnions() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// int c;
|
||||
// };
|
||||
public void testNoErrorsIfThereIsNoConstructorsDefined() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class C {
|
||||
// int i;
|
||||
// C(bool b) { // No warnings.
|
||||
// if (b)
|
||||
// i = 0;
|
||||
// // else - 'i' will be not initialized
|
||||
// }
|
||||
// };
|
||||
public void testNoErrorsIfMemberWasInitializedInOneOfTheIfBranch() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
// class A {
|
||||
// int a;
|
||||
// A(int a) { setA(a); } // No warnings.
|
||||
// A() { getA(); } // 1 warning for: a.
|
||||
// void setA(int a) {
|
||||
// this->a = a;
|
||||
// }
|
||||
// int getA() const {
|
||||
// return a;
|
||||
// }
|
||||
// };
|
||||
public void testUsingMethodsInConstructorWithPreference() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(4);
|
||||
}
|
||||
|
||||
// class A;
|
||||
// void initializeA1(A*);
|
||||
// void initializeA2(A**);
|
||||
// void initializeA3(A&);
|
||||
//
|
||||
// class A {
|
||||
// int a;
|
||||
// A() { initializeA1(this); } // No warnings.
|
||||
// A(int a) { initializeA2(&this); } // No warnings.
|
||||
// A(float a) { initializeA3(*this); } // No warnings.
|
||||
// A(double a) { initializeA3(*(this)); } // No warnings.
|
||||
// };
|
||||
public void testUsingConstMethodsInConstructorWithPreference() {
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkNoErrors();
|
||||
}
|
||||
|
||||
|
||||
// class A {
|
||||
// int a;
|
||||
// A(int a) { setA(a); } // 1 warning for: a.
|
||||
// A() { getA(); } // 1 warning for: a.
|
||||
// void setA(int a) {
|
||||
// this->a = a;
|
||||
// }
|
||||
// int getA() const {
|
||||
// return a;
|
||||
// }
|
||||
// };
|
||||
public void testUsingMethodsInConstructorWithoutPreference() {
|
||||
disableSkipConstructorsWithFCalls();
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(3,4);
|
||||
}
|
||||
|
||||
// class A;
|
||||
// void initializeA1(A*);
|
||||
// void initializeA2(A**);
|
||||
// void initializeA3(A&);
|
||||
//
|
||||
// class A {
|
||||
// int a;
|
||||
// A() { initializeA1(this); } // 1 warning for: a.
|
||||
// A(int a) { initializeA2(&this); } // 1 warning for: a.
|
||||
// A(float a) { initializeA3(*this); } // 1 warning for: a.
|
||||
// A(double a) { initializeA3(*(this)); } // 1 warning for: a.
|
||||
// };
|
||||
public void testUsingConstMethodsInConstructorWithoutPreference() {
|
||||
disableSkipConstructorsWithFCalls();
|
||||
loadCodeAndRun(getAboveComment());
|
||||
checkErrorLines(8,9,10,11);
|
||||
}
|
||||
|
||||
}
|
|
@ -20,6 +20,7 @@ import org.eclipse.cdt.codan.core.internal.checkers.AssignmentInConditionChecker
|
|||
import org.eclipse.cdt.codan.core.internal.checkers.AssignmentToItselfCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.CaseBreakCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.CatchByReferenceTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.ClassMembersInitializationCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.FormatStringCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.NonVirtualDestructorCheckerTest;
|
||||
import org.eclipse.cdt.codan.core.internal.checkers.ProblemBindingCheckerTest;
|
||||
|
@ -56,6 +57,7 @@ public class AutomatedIntegrationSuite extends TestSuite {
|
|||
suite.addTestSuite(AssignmentToItselfCheckerTest.class);
|
||||
suite.addTestSuite(CaseBreakCheckerTest.class);
|
||||
suite.addTestSuite(CatchByReferenceTest.class);
|
||||
suite.addTestSuite(ClassMembersInitializationCheckerTest.class);
|
||||
suite.addTestSuite(FormatStringCheckerTest.class);
|
||||
suite.addTestSuite(NonVirtualDestructorCheckerTest.class);
|
||||
suite.addTestSuite(ProblemBindingCheckerTest.class);
|
||||
|
|
Loading…
Add table
Reference in a new issue