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) { // void test(int a, int b, int c) {
// A(&a, b); // A u = A(&a, b);
// A x(&a, b); // A* v = new A(&a, b);
// A(&a, b, c); // A w(&a, b);
// A y(&a, b, c); // A x = A(&a, b, c);
// A* y = new A(&a, b, c);
// A z(&a, b, c);
// }; // };
public void testConstructorCall_393068() throws Exception { public void testConstructorCall_393068() throws Exception {
AssertionHelper a = getCPPAssertionHelper(); AssertionHelper a = getCPPAssertionHelper();
// a.assertReadWriteFlags("A(&a, b)", "a", READ | WRITE); a.assertReadWriteFlags("= A(&a, b)", "a", READ | WRITE);
// a.assertReadWriteFlags("A(&a, b)", "b", READ | WRITE); a.assertReadWriteFlags("= A(&a, b)", "b", READ | WRITE);
// a.assertReadWriteFlags("x(&a, b)", "a", READ | WRITE); a.assertReadWriteFlags("new A(&a, b)", "a", READ | WRITE);
// a.assertReadWriteFlags("x(&a, b)", "b", READ | WRITE); a.assertReadWriteFlags("new A(&a, b)", "b", READ | WRITE);
// a.assertReadWriteFlags("x(&a, b)", "x", WRITE); a.assertReadWriteFlags("w(&a, b)", "a", READ | WRITE);
a.assertReadWriteFlags("A(&a, b, c)", "a", READ); a.assertReadWriteFlags("w(&a, b)", "b", READ | WRITE);
a.assertReadWriteFlags("A(&a, b, c)", "b", READ); a.assertReadWriteFlags("w(&a, b)", "w", WRITE);
a.assertReadWriteFlags("A(&a, b, c)", "c", READ); a.assertReadWriteFlags("= A(&a, b, c)", "a", READ);
a.assertReadWriteFlags("y(&a, b, c)", "a", READ); a.assertReadWriteFlags("= A(&a, b, c)", "b", READ);
a.assertReadWriteFlags("y(&a, b, c)", "b", READ); a.assertReadWriteFlags("= A(&a, b, c)", "c", READ);
a.assertReadWriteFlags("y(&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 { // 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 * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@ -9,6 +9,7 @@
* John Camelon (IBM) - Initial API and implementation * John Camelon (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Mike Kucera (IBM) * Mike Kucera (IBM)
* Sergey Prigogin (Google)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp; 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.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; 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.ICPPASTNewExpression;
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.ICPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
@ -46,7 +48,7 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
private IASTInitializerClause[] placement; private IASTInitializerClause[] placement;
private IASTTypeId typeId; private IASTTypeId typeId;
private IASTInitializer initializer; private IASTInitializer initializer;
private IASTImplicitName[] implicitNames = null; private IASTImplicitName[] implicitNames;
private boolean isGlobal; private boolean isGlobal;
private boolean isNewTypeId; private boolean isNewTypeId;
@ -163,16 +165,36 @@ public class CPPASTNewExpression extends ASTNode implements ICPPASTNewExpression
@Override @Override
public IASTImplicitName[] getImplicitNames() { public IASTImplicitName[] getImplicitNames() {
if (implicitNames == null) { if (implicitNames == null) {
CPPASTImplicitName operatorName = null;
ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this); ICPPFunction operatorFunction = CPPSemantics.findOverloadedOperator(this);
if (operatorFunction == null || operatorFunction instanceof CPPImplicitFunction) { if (operatorFunction != null && !(operatorFunction instanceof CPPImplicitFunction)) {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY; operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
} else {
CPPASTImplicitName operatorName = new CPPASTImplicitName(operatorFunction.getNameCharArray(), this);
operatorName.setOperator(true); operatorName.setOperator(true);
operatorName.setBinding(operatorFunction); operatorName.setBinding(operatorFunction);
operatorName.setOffsetAndLength(getOffset(), 3); 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 }; implicitNames = new IASTImplicitName[] { operatorName };
} }
} else {
if (constructorName != null) {
implicitNames = new IASTImplicitName[] { constructorName };
} else {
implicitNames = IASTImplicitName.EMPTY_NAME_ARRAY;
}
}
} }
return implicitNames; return implicitNames;

View file

@ -3097,9 +3097,10 @@ public class CPPSemantics {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
if (!(binding instanceof ICPPVariable)) if (!(binding instanceof ICPPVariable))
return null; return null;
IType type;
IType type = ((ICPPVariable) binding).getType();
try { try {
type = SemanticUtil.getNestedType(((ICPPVariable) binding).getType(), TDEF | CVTYPE); type = SemanticUtil.getNestedType(type, TDEF | CVTYPE);
if (!(type instanceof ICPPClassType)) if (!(type instanceof ICPPClassType))
return null; return null;
if (type instanceof ICPPClassTemplate || type instanceof ICPPUnknownType || type instanceof ISemanticProblem) if (type instanceof ICPPClassTemplate || type instanceof ICPPUnknownType || type instanceof ISemanticProblem)
@ -3107,7 +3108,7 @@ public class CPPSemantics {
final ICPPClassType classType = (ICPPClassType) type; final ICPPClassType classType = (ICPPClassType) type;
if (initializer instanceof IASTEqualsInitializer) { if (initializer instanceof IASTEqualsInitializer) {
// Copy initialization // Copy initialization.
IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer; IASTEqualsInitializer eqInit= (IASTEqualsInitializer) initializer;
ICPPASTInitializerClause initClause = (ICPPASTInitializerClause) eqInit.getInitializerClause(); ICPPASTInitializerClause initClause = (ICPPASTInitializerClause) eqInit.getInitializerClause();
final ICPPEvaluation evaluation = initClause.getEvaluation(); final ICPPEvaluation evaluation = initClause.getEvaluation();
@ -3128,7 +3129,7 @@ public class CPPSemantics {
} }
} }
} else if (initializer instanceof ICPPASTInitializerList) { } else if (initializer instanceof ICPPASTInitializerList) {
// List initialization // List initialization.
ICPPEvaluation eval= ((ICPPASTInitializerList) initializer).getEvaluation(); ICPPEvaluation eval= ((ICPPASTInitializerList) initializer).getEvaluation();
if (eval instanceof EvalInitList) { if (eval instanceof EvalInitList) {
Cost c= Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true, name); Cost c= Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true, name);
@ -3139,24 +3140,11 @@ public class CPPSemantics {
} }
} }
} else if (initializer instanceof ICPPASTConstructorInitializer) { } else if (initializer instanceof ICPPASTConstructorInitializer) {
// Direct Initialization // Direct initialization.
final IASTInitializerClause[] arguments = ((ICPPASTConstructorInitializer) initializer).getArguments(); return findImplicitlyCalledConstructor(classType,
CPPASTName astName = new CPPASTName(); (ICPPASTConstructorInitializer) initializer, name);
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;
} else if (initializer == null) { } else if (initializer == null) {
// Default initialization // Default initialization.
ICPPConstructor[] ctors = ClassTypeHelper.getConstructors(classType, name); ICPPConstructor[] ctors = ClassTypeHelper.getConstructors(classType, name);
for (ICPPConstructor ctor : ctors) { for (ICPPConstructor ctor : ctors) {
if (ctor.getRequiredArgumentCount() == 0) if (ctor.getRequiredArgumentCount() == 0)
@ -3169,6 +3157,43 @@ public class CPPSemantics {
return null; 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) { public static ICPPFunction findImplicitlyCalledDestructor(ICPPASTDeleteExpression expr) {
IType t = getTypeOfPointer(expr.getOperand().getExpressionType()); IType t = getTypeOfPointer(expr.getOperand().getExpressionType());
if (!(t instanceof ICPPClassType)) 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.IType;
import org.eclipse.cdt.core.dom.ast.IVariable; 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.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.ICPPASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; 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.ICPPConstructor;
@ -68,7 +69,7 @@ public final class CPPVariableReadWriteFlags extends VariableReadWriteFlags {
private int rwInCtorInitializer(IASTNode node, int indirection, ICPPASTConstructorInitializer parent) { private int rwInCtorInitializer(IASTNode node, int indirection, ICPPASTConstructorInitializer parent) {
IASTNode grand= parent.getParent(); IASTNode grand= parent.getParent();
if (grand instanceof IASTDeclarator) { if (grand instanceof IASTDeclarator || grand instanceof ICPPASTNewExpression) {
// Look for a constructor being called. // Look for a constructor being called.
if (grand instanceof IASTImplicitNameOwner) { if (grand instanceof IASTImplicitNameOwner) {
IASTImplicitName[] names = ((IASTImplicitNameOwner) grand).getImplicitNames(); IASTImplicitName[] names = ((IASTImplicitNameOwner) grand).getImplicitNames();