1
0
Fork 0
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:
Sergey Prigogin 2012-12-04 20:41:54 -08:00
parent c186b2070b
commit 81c9f2d755
4 changed files with 102 additions and 47 deletions

View file

@ -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 {

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* 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
@ -9,6 +9,7 @@
* 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,16 +165,36 @@ 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);
}
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;
}
}
}
return implicitNames;

View file

@ -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))

View file

@ -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();