1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Bug 393068 - Constructor call is treated as write access for arguments

This commit is contained in:
Sergey Prigogin 2012-11-02 17:15:10 +01:00
parent a28a1eb0c6
commit cfd9acad95
4 changed files with 157 additions and 68 deletions

View file

@ -91,7 +91,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification;
@ -1535,6 +1534,43 @@ public class AST2CPPTests extends AST2BaseTest {
}
}
// struct A {
// A(int x);
// A(char x);
// };
//
// A a = A(1);
public void testConstructorCall() throws Exception {
BindingAssertionHelper bh = new BindingAssertionHelper(getAboveComment(), CPP);
ICPPConstructor ctor = bh.assertNonProblem("A(int x)", "A", ICPPConstructor.class);
ICPPClassType classType = bh.assertNonProblem("A(1)", "A", ICPPClassType.class);
assertSame(ctor.getOwner(), classType);
IASTName name = bh.findName("A(1)", "A");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
IBinding ctor2 = implicitNames[0].getBinding();
assertSame(ctor, ctor2);
}
// struct A {
// A(int x);
// };
// struct B {
// operator A();
// };
//
// void test() {
// B b;
// A a = A(b);
// }
public void _testConversionOperator() throws Exception {
BindingAssertionHelper bh = new BindingAssertionHelper(getAboveComment(), CPP);
ICPPMethod oper = bh.assertNonProblem("operator A", "operator A", ICPPMethod.class);
ICPPMethod conv = bh.assertNonProblem("A(b)", "A", ICPPMethod.class);
// This assertion fails because conv is the copy ctor A(const A&), not the conversion operator B::operator A()
assertSame(oper, conv);
}
// namespace A { int x; }
// namespace B = A;
// int f(){ B::x; }
@ -2581,25 +2617,25 @@ public class AST2CPPTests extends AST2BaseTest {
assertTrue(d.getNestedDeclarator().getPointerOperators()[0] instanceof ICPPASTPointerToMember);
}
// struct T1 {
// T1 operator() (int x) {
// return T1(x);
// struct A {
// A operator()(int x) {
// return A(x);
// }
// T1(int) {}
// A(int) {}
// };
public void testBug86336() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ICPPConstructor T1_ctor = (ICPPConstructor) col.getName(6).resolveBinding();
ICPPClassType T1 = (ICPPClassType) col.getName(0).resolveBinding();
assertInstances(col, T1_ctor, 1);
assertInstances(col, T1, 3);
ICPPASTFunctionCallExpression fc= (ICPPASTFunctionCallExpression) col.getName(4).getParent().getParent();
IBinding ctor2 = fc.getImplicitNames()[0].resolveBinding();
assertSame(T1_ctor, ctor2);
BindingAssertionHelper bh = getAssertionHelper();
ICPPClassType clazz = bh.assertNonProblem("A {", "A", ICPPClassType.class);
ICPPConstructor ctor = bh.assertNonProblem("A(int)", "A", ICPPConstructor.class);
ICPPClassType clazz2 = bh.assertNonProblem("A(x)", "A", ICPPClassType.class);
assertSame(clazz, clazz2);
clazz2 = bh.assertNonProblem("A operator", "A", ICPPClassType.class);
assertSame(clazz, clazz2);
IASTName name = bh.findName("A(x)", "A");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
IBinding ctor2 = implicitNames[0].getBinding();
assertSame(ctor, ctor2);
}
// struct S { int i; };
@ -3783,6 +3819,24 @@ public class AST2CPPTests extends AST2BaseTest {
assertTrue(((ITypedef) binding).getType() instanceof IFunctionType);
}
// struct A {
// A(int x);
// };
// typedef A B;
//
// B a = B(1);
public void testTypedefConstructorCall() throws Exception {
BindingAssertionHelper bh = new BindingAssertionHelper(getAboveComment(), CPP);
ICPPConstructor ctor = bh.assertNonProblem("A(int x)", "A", ICPPConstructor.class);
ITypedef typedef = bh.assertNonProblem("B(1)", "B", ITypedef.class);
assertSame(ctor.getOwner(), typedef.getType());
IASTName name = bh.findName("B(1)", "B");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
IBinding ctor2 = implicitNames[0].getBinding();
assertSame(ctor, ctor2);
}
// void f(int);
// void foo(){
// f((1, 2));

View file

@ -18,6 +18,9 @@ import static org.eclipse.cdt.core.parser.ParserLanguage.CPP;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getNestedType;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
import java.io.IOException;
import junit.framework.TestSuite;
import org.eclipse.cdt.core.dom.IName;
@ -29,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTNodeSelector;
@ -50,7 +54,6 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
@ -89,6 +92,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
import org.eclipse.cdt.internal.core.parser.ParserException;
public class AST2TemplateTests extends AST2BaseTest {
@ -111,6 +115,11 @@ public class AST2TemplateTests extends AST2BaseTest {
return parseAndCheckBindings(code, CPP);
}
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
String code= getAboveComment();
return new BindingAssertionHelper(code, true);
}
public void testBasicClassTemplate() throws Exception {
IASTTranslationUnit tu = parse("template <class T> class A{ T t; };", CPP); //$NON-NLS-1$
CPPNameCollector col = new CPPNameCollector();
@ -1719,23 +1728,19 @@ public class AST2TemplateTests extends AST2BaseTest {
// void m(){
// f(A<int>(1));
// }
public void testBug99254() throws Exception{
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding();
ICPPFunction f = (ICPPFunction) col.getName(5).resolveBinding();
final IASTName typeConversion = col.getName(11);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
public void testBug99254_1() throws Exception {
BindingAssertionHelper bh= getAssertionHelper();
ICPPConstructor ctor = bh.assertNonProblem("A(T t)", "A", ICPPConstructor.class);
ICPPSpecialization spec = bh.assertNonProblem("A<int>(1)", "A<int>", ICPPSpecialization.class);
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(f, col.getName(10).resolveBinding());
IASTName name = bh.findName("A<int>(1)", "A<int>");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
ICPPSpecialization ctor2 = (ICPPSpecialization) implicitNames[0].getBinding();
assertSame(ctor, ctor2.getSpecializedBinding());
ICPPFunction f = bh.assertNonProblem("f(A<int> a)", "f", ICPPFunction.class);
ICPPFunction f2 = bh.assertNonProblem("f(A<int>(1))", "f", ICPPFunction.class);
assertSame(f, f2);
}
// namespace core {
@ -1744,67 +1749,59 @@ public class AST2TemplateTests extends AST2BaseTest {
// };
// }
// class B {
// int add(const core::A<int> &rect);
// int add(const core::A<int>& rect);
// };
// void f(B* b){
// b->add(core::A<int>(10, 2));
// }
public void testBug99254_2() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ICPPConstructor ctor = (ICPPConstructor) col.getName(3).resolveBinding();
ICPPMethod add = (ICPPMethod) col.getName(9).resolveBinding();
final IASTName typeConversion = col.getName(20);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
BindingAssertionHelper bh= getAssertionHelper();
ICPPConstructor ctor = bh.assertNonProblem("A(T x, T y)", "A", ICPPConstructor.class);
ICPPSpecialization spec = bh.assertNonProblem("A<int>(10, 2)", "A<int>", ICPPSpecialization.class);
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(add, col.getName(19).resolveBinding());
IASTName name = bh.findName("A<int>(10, 2)", "A<int>");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
ICPPSpecialization ctor2 = (ICPPSpecialization) implicitNames[0].getBinding();
assertSame(ctor, ctor2.getSpecializedBinding());
ICPPMethod add = bh.assertNonProblem("add(const core::A<int>& rect)", "add", ICPPMethod.class);
ICPPMethod add2 = bh.assertNonProblem("b->add(core::A<int>(10, 2))", "add", ICPPMethod.class);
assertSame(add, add2);
}
// template <class T> class A { A(T); };
// typedef signed int s32;
// class B {
// int add(const A<s32> &rect);
// int add(const A<s32>& rect);
// };
// void f(B* b){
// b->add(A<int>(10));
// }
public void testBug99254_3() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ICPPConstructor ctor = (ICPPConstructor) col.getName(2).resolveBinding();
ICPPMethod add = (ICPPMethod) col.getName(7).resolveBinding();
final IASTName typeConversion = col.getName(17);
ICPPSpecialization spec = (ICPPSpecialization) typeConversion.resolveBinding();
BindingAssertionHelper bh= getAssertionHelper();
ICPPConstructor ctor = bh.assertNonProblem("A(T)", "A", ICPPConstructor.class);
ICPPSpecialization spec = bh.assertNonProblem("A<int>(10)", "A<int>", ICPPSpecialization.class);
assertSame(ctor.getOwner(), spec.getSpecializedBinding());
final ICPPASTFunctionCallExpression fcall = (ICPPASTFunctionCallExpression) typeConversion.getParent().getParent();
final IBinding ctorSpec = fcall.getImplicitNames()[0].resolveBinding();
assertSame(ctor, (((ICPPSpecialization) ctorSpec).getSpecializedBinding()));
assertSame(add, col.getName(16).resolveBinding());
IASTName name = bh.findName("A<int>(10)", "A<int>");
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) name.getParent().getParent()).getImplicitNames();
assertEquals(1, implicitNames.length);
ICPPSpecialization ctor2 = (ICPPSpecialization) implicitNames[0].getBinding();
assertSame(ctor, ctor2.getSpecializedBinding());
ICPPMethod add = bh.assertNonProblem("add(const A<s32>& rect)", "add", ICPPMethod.class);
ICPPMethod add2 = bh.assertNonProblem("b->add(A<int>(10))", "add", ICPPMethod.class);
assertSame(add, add2);
}
public void testBug98666() throws Exception {
CPPASTNameBase.sAllowNameComputation= true;
IASTTranslationUnit tu = parse("A::template B<T> b;", CPP); //$NON-NLS-1$
IASTTranslationUnit tu = parse("A::template B<T> b;", CPP);
CPPNameCollector col = new CPPNameCollector();
tu.accept(col);
ICPPASTQualifiedName qn = (ICPPASTQualifiedName) col.getName(0);
IASTName[] ns = qn.getNames();
assertTrue(ns[1] instanceof ICPPASTTemplateId);
assertEquals(ns[1].toString(), "B<T>"); //$NON-NLS-1$
assertEquals(ns[1].toString(), "B<T>");
}
// template <class T> struct A{

View file

@ -159,6 +159,32 @@ public class VariableReadWriteFlagsTest extends AST2BaseTest {
a.assertReadWriteFlags("g(&a, b, c)", "c", READ);
}
// struct A {
// A(int* x, int& y);
// A(const int* x, const int& y, int z);
// };
//
// void test(int a, int b, int c) {
// A(&a, b);
// A x(&a, b);
// A(&a, b, c);
// A y(&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);
}
// struct A {
// void m();
// void mc() const;

View file

@ -28,6 +28,8 @@ import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTImplicitName;
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -41,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IVariable;
@ -188,6 +191,15 @@ public abstract class VariableReadWriteFlags {
final IType type= functionNameExpression.getExpressionType();
if (type instanceof IFunctionType) {
return rwArgumentForFunctionCall((IFunctionType) type, i, indirection);
} else {
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) funcCall).getImplicitNames();
if (implicitNames.length == 1) {
IASTImplicitName name = implicitNames[0];
IBinding binding = name.resolveBinding();
if (binding instanceof IFunction) {
return rwArgumentForFunctionCall(((IFunction) binding).getType(), i, indirection);
}
}
}
}
break;