mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 393068 - Constructor call is treated as write access for arguments
This commit is contained in:
parent
c186b2070b
commit
81c9f2d755
4 changed files with 102 additions and 47 deletions
|
@ -165,24 +165,31 @@ public class VariableReadWriteFlagsTest extends AST2BaseTest {
|
|||
// };
|
||||
//
|
||||
// void test(int a, int b, int c) {
|
||||
// A(&a, b);
|
||||
// A x(&a, b);
|
||||
// A(&a, b, c);
|
||||
// A y(&a, b, c);
|
||||
// A u = A(&a, b);
|
||||
// A* v = new A(&a, b);
|
||||
// A w(&a, b);
|
||||
// A x = A(&a, b, c);
|
||||
// A* y = new A(&a, b, c);
|
||||
// A z(&a, b, c);
|
||||
// };
|
||||
public void testConstructorCall_393068() throws Exception {
|
||||
AssertionHelper a = getCPPAssertionHelper();
|
||||
// a.assertReadWriteFlags("A(&a, b)", "a", READ | WRITE);
|
||||
// a.assertReadWriteFlags("A(&a, b)", "b", READ | WRITE);
|
||||
// a.assertReadWriteFlags("x(&a, b)", "a", READ | WRITE);
|
||||
// a.assertReadWriteFlags("x(&a, b)", "b", READ | WRITE);
|
||||
// a.assertReadWriteFlags("x(&a, b)", "x", WRITE);
|
||||
a.assertReadWriteFlags("A(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("A(&a, b, c)", "b", READ);
|
||||
a.assertReadWriteFlags("A(&a, b, c)", "c", READ);
|
||||
a.assertReadWriteFlags("y(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("y(&a, b, c)", "b", READ);
|
||||
a.assertReadWriteFlags("y(&a, b, c)", "c", READ);
|
||||
a.assertReadWriteFlags("= A(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("= A(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("new A(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("new A(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("w(&a, b)", "a", READ | WRITE);
|
||||
a.assertReadWriteFlags("w(&a, b)", "b", READ | WRITE);
|
||||
a.assertReadWriteFlags("w(&a, b)", "w", WRITE);
|
||||
a.assertReadWriteFlags("= A(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("= A(&a, b, c)", "b", READ);
|
||||
a.assertReadWriteFlags("= A(&a, b, c)", "c", READ);
|
||||
a.assertReadWriteFlags("new A(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("new A(&a, b, c)", "b", READ);
|
||||
a.assertReadWriteFlags("new A(&a, b, c)", "c", READ);
|
||||
a.assertReadWriteFlags("z(&a, b, c)", "a", READ);
|
||||
a.assertReadWriteFlags("z(&a, b, c)", "b", READ);
|
||||
a.assertReadWriteFlags("z(&a, b, c)", "c", READ);
|
||||
}
|
||||
|
||||
// struct A {
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2011 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2012 IBM Corporation 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Mike Kucera (IBM)
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Mike Kucera (IBM)
|
||||
* Sergey Prigogin (Google)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
|
@ -30,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IArrayType;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
|
@ -46,7 +48,7 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
|
|||
private IASTInitializerClause[] placement;
|
||||
private IASTTypeId typeId;
|
||||
private IASTInitializer initializer;
|
||||
private IASTImplicitName[] implicitNames = null;
|
||||
private IASTImplicitName[] implicitNames;
|
||||
private boolean isGlobal;
|
||||
private boolean isNewTypeId;
|
||||
|
||||
|
@ -163,15 +165,35 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
|
|||
@Override
|
||||
public IASTImplicitName[] getImplicitNames() {
|
||||
if (implicitNames == null) {
|
||||
CPPASTImplicitName operatorName = null;
|
||||
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
|
||||
if (operatorFunction == null || operatorFunction instanceof CPPImplicitFunction) {
|
||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
} else {
|
||||
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
|
||||
if (operatorFunction != null && !(operatorFunction instanceof CPPImplicitFunction)) {
|
||||
operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
|
||||
operatorName.setOperator(true);
|
||||
operatorName.setBinding(operatorFunction);
|
||||
operatorName.setOffsetAndLength(getOffset(), 3);
|
||||
implicitNames = new IASTImplicitName[] { operatorName };
|
||||
}
|
||||
|
||||
CPPASTImplicitName constructorName = null;
|
||||
ICPPConstructor constructor = CPPSemantics.findImplicitlyCalledConstructor(this);
|
||||
if (constructor != null) {
|
||||
constructorName = new CPPASTImplicitName(constructor.getNameCharArray(), this);
|
||||
constructorName.setBinding(constructor);
|
||||
constructorName.setOffsetAndLength((ASTNode) getTypeId());
|
||||
}
|
||||
|
||||
if (operatorName != null) {
|
||||
if (constructorName != null) {
|
||||
implicitNames = new IASTImplicitName[] { operatorName, constructorName };
|
||||
} else {
|
||||
implicitNames = new IASTImplicitName[] { operatorName };
|
||||
}
|
||||
} else {
|
||||
if (constructorName != null) {
|
||||
implicitNames = new IASTImplicitName[] { constructorName };
|
||||
} else {
|
||||
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3097,9 +3097,10 @@ public class CPPSemantics {
|
|||
IBinding binding = name.resolveBinding();
|
||||
if (!(binding instanceof ICPPVariable))
|
||||
return null;
|
||||
IType type;
|
||||
|
||||
IType type = ((ICPPVariable) binding).getType();
|
||||
try {
|
||||
type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE);
|
||||
type = SemanticUtil.getNestedType(type, TDEF | CVTYPE);
|
||||
if (!(type instanceof ICPPClassType))
|
||||
return null;
|
||||
if (type instanceof ICPPClassTemplate || type instanceof ICPPUnknownType || type instanceof ISemanticProblem)
|
||||
|
@ -3107,7 +3108,7 @@ public class CPPSemantics {
|
|||
|
||||
final ICPPClassType classType = (ICPPClassType) type;
|
||||
if (initializer instanceof IASTEqualsInitializer) {
|
||||
// Copy initialization
|
||||
// Copy initialization.
|
||||
IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
|
||||
ICPPASTInitializerClause initClause = (ICPPASTInitializerClause) eqInit.getInitializerClause();
|
||||
final ICPPEvaluation evaluation = initClause.getEvaluation();
|
||||
|
@ -3128,7 +3129,7 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
} else if (initializer instanceof ICPPASTInitializerList) {
|
||||
// List initialization
|
||||
// List initialization.
|
||||
ICPPEvaluation eval= ((ICPPASTInitializerList) initializer).getEvaluation();
|
||||
if (eval instanceof EvalInitList) {
|
||||
Cost c= Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true, name);
|
||||
|
@ -3139,24 +3140,11 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
} else if (initializer instanceof ICPPASTConstructorInitializer) {
|
||||
// Direct Initialization
|
||||
final IASTInitializerClause[] arguments = ((ICPPASTConstructorInitializer) initializer).getArguments();
|
||||
CPPASTName astName = new CPPASTName();
|
||||
astName.setName(classType.getNameCharArray());
|
||||
astName.setOffsetAndLength((ASTNode) name);
|
||||
CPPASTIdExpression idExp = new CPPASTIdExpression(astName);
|
||||
idExp.setParent(name.getParent());
|
||||
idExp.setPropertyInParent(IASTFunctionCallExpression.FUNCTION_NAME);
|
||||
|
||||
LookupData data = new LookupData(astName);
|
||||
data.setFunctionArguments(false, arguments);
|
||||
data.qualified = true;
|
||||
data.foundItems = ClassTypeHelper.getConstructors(classType, name);
|
||||
binding = resolveAmbiguities(data);
|
||||
if (binding instanceof ICPPConstructor)
|
||||
return (ICPPConstructor) binding;
|
||||
// Direct initialization.
|
||||
return findImplicitlyCalledConstructor(classType,
|
||||
(ICPPASTConstructorInitializer) initializer, name);
|
||||
} else if (initializer == null) {
|
||||
// Default initialization
|
||||
// Default initialization.
|
||||
ICPPConstructor[] ctors = ClassTypeHelper.getConstructors(classType, name);
|
||||
for (ICPPConstructor ctor : ctors) {
|
||||
if (ctor.getRequiredArgumentCount() == 0)
|
||||
|
@ -3169,6 +3157,43 @@ public class CPPSemantics {
|
|||
return null;
|
||||
}
|
||||
|
||||
public static ICPPConstructor findImplicitlyCalledConstructor(ICPPASTNewExpression expr) {
|
||||
IType type = getNestedType(expr.getExpressionType(), TDEF | REF | CVTYPE);
|
||||
if (!(type instanceof IPointerType))
|
||||
return null;
|
||||
type = ((IPointerType) type).getType();
|
||||
IASTInitializer initializer = expr.getInitializer();
|
||||
if (type instanceof ICPPClassType && initializer instanceof ICPPASTConstructorInitializer) {
|
||||
return findImplicitlyCalledConstructor((ICPPClassType) type,
|
||||
(ICPPASTConstructorInitializer) initializer, expr.getTypeId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static ICPPConstructor findImplicitlyCalledConstructor(ICPPClassType classType,
|
||||
ICPPASTConstructorInitializer initializer, IASTNode typeId) {
|
||||
final IASTInitializerClause[] arguments = initializer.getArguments();
|
||||
CPPASTName astName = new CPPASTName();
|
||||
astName.setName(classType.getNameCharArray());
|
||||
astName.setOffsetAndLength((ASTNode) typeId);
|
||||
CPPASTIdExpression idExp = new CPPASTIdExpression(astName);
|
||||
idExp.setParent(typeId.getParent());
|
||||
idExp.setPropertyInParent(IASTFunctionCallExpression.FUNCTION_NAME);
|
||||
|
||||
LookupData data = new LookupData(astName);
|
||||
data.setFunctionArguments(false, arguments);
|
||||
data.qualified = true;
|
||||
data.foundItems = ClassTypeHelper.getConstructors(classType, typeId);
|
||||
IBinding binding;
|
||||
try {
|
||||
binding = resolveAmbiguities(data);
|
||||
if (binding instanceof ICPPConstructor)
|
||||
return (ICPPConstructor) binding;
|
||||
} catch (DOMException e) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) {
|
||||
IType t = getTypeOfPointer(expr.getOperand().getExpressionType());
|
||||
if (!(t instanceof ICPPClassType))
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
|||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IVariable;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
|
||||
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;
|
||||
|
@ -68,7 +69,7 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
|
|||
|
||||
private int rwInCtorInitializer(IASTNode node, int indirection, ICPPASTConstructorInitializer parent) {
|
||||
IASTNode grand= parent.getParent();
|
||||
if (grand instanceof IASTDeclarator) {
|
||||
if (grand instanceof IASTDeclarator || grand instanceof ICPPASTNewExpression) {
|
||||
// Look for a constructor being called.
|
||||
if (grand instanceof IASTImplicitNameOwner) {
|
||||
IASTImplicitName[] names = ((IASTImplicitNameOwner) grand).getImplicitNames();
|
||||
|
|
Loading…
Add table
Reference in a new issue