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:
parent
a28a1eb0c6
commit
cfd9acad95
4 changed files with 157 additions and 68 deletions
|
@ -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));
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue