From 53bc0f10e6d414ea628569ea492bd7f1a7bb758b Mon Sep 17 00:00:00 2001 From: Marc-Andre Laperle Date: Wed, 7 Mar 2012 20:36:34 -0500 Subject: [PATCH] Bug 368420 - FP in members not initialized in in copy constructor --- .../ClassMembersInitializationChecker.java | 24 +++++++--- ...ClassMembersInitializationCheckerTest.java | 46 +++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) 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 index 9ba327eb8a5..546b2fef333 100644 --- 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 @@ -18,6 +18,7 @@ import java.util.Stack; 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.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; @@ -67,11 +68,12 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker { // NOTE: Classes can be nested and even can be declared in constructors of the other classes private final Stack< Set > constructorsStack = new Stack< Set >(); + private boolean skipConstructorsWithFCalls = skipConstructorsWithFCalls(); OnEachClass() { shouldVisitDeclarations = true; shouldVisitNames = true; - shouldVisitExpressions = skipConstructorsWithFCalls(); + shouldVisitExpressions = true; } @Override @@ -102,10 +104,11 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker { @Override public int visit(IASTExpression expression) { - if (!constructorsStack.empty() && expression instanceof IASTFunctionCallExpression) { + boolean skipCurrentConstructor = false; + + if (skipConstructorsWithFCalls && !constructorsStack.empty() && expression instanceof IASTFunctionCallExpression) { Set actualConstructorFields = constructorsStack.peek(); if (!actualConstructorFields.isEmpty()) { - boolean skipCurrentConstructor = false; IASTFunctionCallExpression fCall = (IASTFunctionCallExpression)expression; IASTExpression fNameExp = fCall.getFunctionNameExpression(); if (fNameExp instanceof IASTIdExpression) { @@ -126,11 +129,20 @@ public class ClassMembersInitializationChecker extends AbstractIndexAstChecker { } } } - if (skipCurrentConstructor) { - constructorsStack.peek().clear(); - } } } + + // Bug 368420 - Skip constructor if pattern is *this = toBeCopied; + if(expression instanceof IASTBinaryExpression) { + IASTBinaryExpression binaryExpression = (IASTBinaryExpression) expression; + if(referencesThis(binaryExpression.getOperand1()) && binaryExpression.getOperand1().isLValue()) { + skipCurrentConstructor = true; + } + } + + if (skipCurrentConstructor) { + constructorsStack.peek().clear(); + } return PROCESS_CONTINUE; } 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 index 4e86f38be5d..55a23193970 100644 --- 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 @@ -497,4 +497,50 @@ public class ClassMembersInitializationCheckerTest extends CheckerTestCase { runOnProject(); checkNoErrors(); } + + //class D { + // int field; + // D(const D& toBeCopied) { + // *this = toBeCopied; + // }; + //}; + public void testBug368420_assignThis() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //class D { + // int field; + // D(const D& toBeCopied) { + // *(&(*this)) = toBeCopied; + // }; + //}; + public void testBug368420_assignThisUnaryExpressions() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } + + //class D { + // int field; + // D(const D& toBeCopied) { + // this = toBeCopied; + // }; + //}; + public void testBug368420_assignThisNonLValue() throws Exception { + loadCodeAndRun(getAboveComment()); + checkErrorLines(3); + } + + //class D { + // int field; + // D(); + // D(const D& toBeCopied) { + // D temp; + // temp = *(&(*this)) = toBeCopied; + // }; + //}; + public void testBug368420_assignThisMultiBinaryExpressions() throws Exception { + loadCodeAndRun(getAboveComment()); + checkNoErrors(); + } }