summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Gorenkov2011-07-06 02:12:45 (EDT)
committer Marc-Andre Laperle2011-07-06 02:34:49 (EDT)
commit3b6f6642b801502b9c6125aec81bcc82213014c6 (patch)
tree9c7489c6f4fee8f2d21abd6e5a5cccf19638fff6
parent82a3d0c2809615e92303ce430ada5f5840ef9333 (diff)
downloadorg.eclipse.cdt-3b6f6642b801502b9c6125aec81bcc82213014c6.zip
org.eclipse.cdt-3b6f6642b801502b9c6125aec81bcc82213014c6.tar.gz
org.eclipse.cdt-3b6f6642b801502b9c6125aec81bcc82213014c6.tar.bz2
Bug 339795 - [checker] Checker that finds class members that are not
initialized in constructor
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties6
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/plugin.xml14
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java3
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.properties3
-rw-r--r--codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ClassMembersInitializationChecker.java222
-rw-r--r--codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java480
-rw-r--r--codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java2
7 files changed, 727 insertions, 3 deletions
diff --git a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
index a59ba9e..3d003da 100644
--- a/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
+++ b/codan/org.eclipse.cdt.codan.checkers/OSGI-INF/l10n/bundle.properties
@@ -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
diff --git a/codan/org.eclipse.cdt.codan.checkers/plugin.xml b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
index b8e6b7f..0f3f1c7 100644
--- a/codan/org.eclipse.cdt.codan.checkers/plugin.xml
+++ b/codan/org.eclipse.cdt.codan.checkers/plugin.xml
@@ -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>
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java
index ee770a9..8a4ad7e 100644
--- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.java
@@ -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;
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.properties b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.properties
index 2aefeb0..b219b97 100644
--- a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.properties
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/CheckersMessages.properties
@@ -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
diff --git a/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ClassMembersInitializationChecker.java b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ClassMembersInitializationChecker.java
new file mode 100644
index 0000000..c0d1604
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.checkers/src/org/eclipse/cdt/codan/internal/checkers/ClassMembersInitializationChecker.java
@@ -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);
+ }
+
+}
diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java
new file mode 100644
index 0000000..a0b261b
--- /dev/null
+++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/internal/checkers/ClassMembersInitializationCheckerTest.java
@@ -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);
+ }
+
+}
diff --git a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
index 7958a4b..b70376f 100644
--- a/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
+++ b/codan/org.eclipse.cdt.codan.core.test/src/org/eclipse/cdt/codan/core/test/AutomatedIntegrationSuite.java
@@ -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);