mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
238232: fix conversions relating to implicit object argument, and some follow on exposed bugs
This commit is contained in:
parent
a736d7bf98
commit
b23fa116f6
8 changed files with 304 additions and 67 deletions
|
@ -5795,4 +5795,120 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
ICPPFunction fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class);
|
ICPPFunction fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class);
|
||||||
assertNotSame(fn1, fn2);
|
assertNotSame(fn1, fn2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class A;
|
||||||
|
//
|
||||||
|
// void foo(A* a) {}
|
||||||
|
// void foo(const A* a) {}
|
||||||
|
// void foo(volatile A* a) {}
|
||||||
|
// void foo(const volatile A* a) {}
|
||||||
|
//
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// void member1() { foo(this);/*1*/ }
|
||||||
|
// void member2() const { foo(this);/*2*/ }
|
||||||
|
// void member3() volatile { foo(this);/*3*/ }
|
||||||
|
// void member4() const volatile { foo(this);/*4*/ }
|
||||||
|
// };
|
||||||
|
public void testThisType() throws Exception {
|
||||||
|
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ICPPFunction pt1= ba.assertNonProblem("foo(this);/*1*/", 3, ICPPFunction.class);
|
||||||
|
ICPPFunction pt2= ba.assertNonProblem("foo(this);/*2*/", 3, ICPPFunction.class);
|
||||||
|
ICPPFunction pt3= ba.assertNonProblem("foo(this);/*3*/", 3, ICPPFunction.class);
|
||||||
|
ICPPFunction pt4= ba.assertNonProblem("foo(this);/*4*/", 3, ICPPFunction.class);
|
||||||
|
|
||||||
|
IType t1= ((IPointerType)pt1.getType().getParameterTypes()[0]).getType();
|
||||||
|
IQualifierType t2= (IQualifierType) ((IPointerType) pt2.getType().getParameterTypes()[0]).getType();
|
||||||
|
IQualifierType t3= (IQualifierType)((IPointerType) pt3.getType().getParameterTypes()[0]).getType();
|
||||||
|
IQualifierType t4= (IQualifierType)((IPointerType) pt4.getType().getParameterTypes()[0]).getType();
|
||||||
|
|
||||||
|
assertTrue(!(t1 instanceof IQualifierType));
|
||||||
|
assertTrue(t2.isConst()); assertTrue(!t2.isVolatile());
|
||||||
|
assertTrue(!t3.isConst()); assertTrue(t3.isVolatile());
|
||||||
|
assertTrue(t4.isConst()); assertTrue(t4.isVolatile());
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// void foo() {}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void ref() {
|
||||||
|
// A a1= *new A();
|
||||||
|
// a1->foo();/*1*/
|
||||||
|
// A* a2= new A();
|
||||||
|
// a2->foo();/*2*/
|
||||||
|
// }
|
||||||
|
public void testMemberAccessOperator_a() throws Exception {
|
||||||
|
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertProblem("foo();/*1*/", 3);
|
||||||
|
ba.assertNonProblem("foo();/*2*/", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// void foo() {};
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// class B {
|
||||||
|
// public:
|
||||||
|
// void foo() {};
|
||||||
|
// A* operator->() {return new A();}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void ref() {
|
||||||
|
// B b= *new B();
|
||||||
|
// b->foo();/*1*/
|
||||||
|
// B* b2= new B();
|
||||||
|
// b2->foo();/*2*/
|
||||||
|
// }
|
||||||
|
public void testMemberAccessOperator_b() throws Exception {
|
||||||
|
BindingAssertionHelper ba=new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ICPPMethod m1= ba.assertNonProblem("foo();/*1*/", 3, ICPPMethod.class);
|
||||||
|
ICPPMethod m2= ba.assertNonProblem("foo();/*2*/", 3, ICPPMethod.class);
|
||||||
|
assertEquals(m1.getClassOwner().getName(), "A");
|
||||||
|
assertEquals(m2.getClassOwner().getName(), "B");
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A { public: void foo(); };
|
||||||
|
// class B { public: A* operator->() {return new A();} };
|
||||||
|
// class C { public: B operator->() {return *new B();} };
|
||||||
|
//
|
||||||
|
// void ref() {
|
||||||
|
// C c;
|
||||||
|
// c->foo();/**/ // refers to A::foo
|
||||||
|
// }
|
||||||
|
public void testMemberAccessOperator_c() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertNonProblem("foo();/**/", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A { public: void foo(); };
|
||||||
|
// class B { public: A* operator->() {return new A();} };
|
||||||
|
// class C { public: B* operator->() {return new B();} };
|
||||||
|
//
|
||||||
|
// void ref() {
|
||||||
|
// C c;
|
||||||
|
// c->foo();/**/ // expect problem - foo is not in B
|
||||||
|
// }
|
||||||
|
public void testMemberAccessOperator_d() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertProblem("foo();/**/", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A { public: void foo(); };
|
||||||
|
// typedef A A2;
|
||||||
|
// class B { public: A2* operator->() {return new A();} };
|
||||||
|
// typedef B B2;
|
||||||
|
// class C { public: B2 operator->() {return *new B();} };
|
||||||
|
//
|
||||||
|
// typedef C C2;
|
||||||
|
// void ref() {
|
||||||
|
// C2 c;
|
||||||
|
// c->foo();/**/ // refers to A::foo
|
||||||
|
// }
|
||||||
|
public void testMemberAccessOperator_e() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertNonProblem("foo();/**/", 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2970,4 +2970,54 @@ public class AST2TemplateTests extends AST2BaseTest {
|
||||||
ICPPSpecialization ctps= ba.assertNonProblem("C<A,5L>", 7, ICPPSpecialization.class, ICPPClassType.class);
|
ICPPSpecialization ctps= ba.assertNonProblem("C<A,5L>", 7, ICPPSpecialization.class, ICPPClassType.class);
|
||||||
assertFalse(ctps instanceof ICPPTemplateInstance);
|
assertFalse(ctps instanceof ICPPTemplateInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// A(const A& a) {}
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// class B : A {
|
||||||
|
// public:
|
||||||
|
// B(const B<T>& other) : A(other) {}
|
||||||
|
// };
|
||||||
|
public void testChainInitializerLookupThroughDeferredClassBase() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertNonProblem("A(other", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// class A {};
|
||||||
|
//
|
||||||
|
// class B {
|
||||||
|
// public:
|
||||||
|
// void foo(const A& b);
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// class C : public B {
|
||||||
|
// public:
|
||||||
|
// void foo(T *t) {
|
||||||
|
// B::foo(static_cast<A*>(t));
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
public void testMemberLookupThroughDeferredClassBase() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertNonProblem("foo(s", 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <class T>
|
||||||
|
// class A {
|
||||||
|
// public:
|
||||||
|
// inline int foo() const;
|
||||||
|
// inline int bar() const;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <class T>
|
||||||
|
// inline int A<T>::bar() const {
|
||||||
|
// return foo();
|
||||||
|
// }
|
||||||
|
public void testMemberReferenceFromTemplatedMethodDefinition_238232() throws Exception {
|
||||||
|
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true);
|
||||||
|
ba.assertNonProblem("foo();", 3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1275,7 +1275,7 @@ public class CompleteParser2Tests extends BaseTestCase {
|
||||||
buff.append( " void f_SD_01(); \n"); //$NON-NLS-1$
|
buff.append( " void f_SD_01(); \n"); //$NON-NLS-1$
|
||||||
buff.append( "}; \n"); //$NON-NLS-1$
|
buff.append( "}; \n"); //$NON-NLS-1$
|
||||||
buff.append( "int main(){ \n"); //$NON-NLS-1$
|
buff.append( "int main(){ \n"); //$NON-NLS-1$
|
||||||
buff.append( " SD_01 a = new SD_01(); \n"); //$NON-NLS-1$ // REFERENCE SD_01 * 2
|
buff.append( " SD_01* a = new SD_01(); \n"); //$NON-NLS-1$ // REFERENCE SD_01 * 2
|
||||||
buff.append( " a->f_SD_01(); \n"); //$NON-NLS-1$ // REFERENCE a && REFERENCE f_SD_01
|
buff.append( " a->f_SD_01(); \n"); //$NON-NLS-1$ // REFERENCE a && REFERENCE f_SD_01
|
||||||
buff.append( "} \n"); //$NON-NLS-1$
|
buff.append( "} \n"); //$NON-NLS-1$
|
||||||
buff.append( "void SD_01::f_SD_01() \n"); //$NON-NLS-1$ // REFERENCE SD_01
|
buff.append( "void SD_01::f_SD_01() \n"); //$NON-NLS-1$ // REFERENCE SD_01
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||||
|
|
||||||
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateType;
|
||||||
|
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.getUltimateTypeUptoPointers;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -61,7 +62,9 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunction;
|
import org.eclipse.cdt.core.dom.ast.IFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
import org.eclipse.cdt.core.dom.ast.IFunctionType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IParameter;
|
import org.eclipse.cdt.core.dom.ast.IParameter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IPointerType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IQualifierType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||||
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;
|
||||||
|
@ -126,6 +129,8 @@ import org.eclipse.cdt.core.parser.util.ObjectSet;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||||
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.ProblemBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||||
|
@ -138,6 +143,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownScope;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnknownScope;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDirective;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVariable;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalTemplateInstantiator;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalTemplateInstantiator;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
|
||||||
|
@ -2372,6 +2378,80 @@ public class CPPSemantics {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to
|
||||||
|
* when chaining overloaded class member access operators <code>operator->()</code> calls.
|
||||||
|
* @param fieldReference
|
||||||
|
* @return the type the field owner expression ultimately evaluates to when chaining overloaded
|
||||||
|
* class member access operators <code>operator->()</code> calls.
|
||||||
|
* @throws DOMException
|
||||||
|
*/
|
||||||
|
public static IType getChainedMemberAccessOperatorReturnType(ICPPASTFieldReference fieldReference) throws DOMException {
|
||||||
|
IASTExpression owner = fieldReference.getFieldOwner();
|
||||||
|
IType result= CPPVisitor.getExpressionType(owner);
|
||||||
|
|
||||||
|
if (fieldReference.isPointerDereference()) {
|
||||||
|
IType type= getUltimateTypeUptoPointers(result);
|
||||||
|
boolean needCheckClassMemberAccessOperator= true;
|
||||||
|
if(type instanceof IPointerType) {
|
||||||
|
type= getUltimateTypeUptoPointers(((IPointerType) type).getType());
|
||||||
|
if(type instanceof ICPPClassType) {
|
||||||
|
needCheckClassMemberAccessOperator= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(needCheckClassMemberAccessOperator) {
|
||||||
|
IType temp= result;
|
||||||
|
result= null;
|
||||||
|
|
||||||
|
// bug 205964: as long as the type is a class type, recurse.
|
||||||
|
// Be defensive and allow a max of 10 levels.
|
||||||
|
for (int j = 0; j < 10; j++) {
|
||||||
|
IType uTemp= getUltimateTypeUptoPointers(temp);
|
||||||
|
if (uTemp instanceof ICPPClassType) {
|
||||||
|
/*
|
||||||
|
* 13.5.6-1: An expression x->m is interpreted as (x.operator->())->m for a
|
||||||
|
* class object x of type T
|
||||||
|
*
|
||||||
|
* Construct an AST fragment for x.operator-> which the lookup routines can
|
||||||
|
* examine for type information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
CPPASTName x= new CPPASTName();
|
||||||
|
boolean isConst= false, isVolatile= false;
|
||||||
|
if(temp instanceof IQualifierType) {
|
||||||
|
isConst= ((IQualifierType)temp).isConst();
|
||||||
|
isVolatile= ((IQualifierType)temp).isVolatile();
|
||||||
|
}
|
||||||
|
x.setBinding(createVariable(x, uTemp, isConst, isVolatile));
|
||||||
|
|
||||||
|
IASTName arw= new CPPASTName(OverloadableOperator.ARROW.toCharArray());
|
||||||
|
IASTFieldReference innerFR= new CPPASTFieldReference(arw, new CPPASTIdExpression(x));
|
||||||
|
innerFR.setParent(fieldReference); // connect to the AST
|
||||||
|
|
||||||
|
ICPPFunction op = CPPSemantics.findOperator(innerFR, (ICPPClassType) uTemp);
|
||||||
|
if (op != null) {
|
||||||
|
result= temp= op.getType().getReturnType();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ICPPVariable createVariable(IASTName name, final IType type, final boolean isConst, final boolean isVolatile) {
|
||||||
|
return new CPPVariable(name) {
|
||||||
|
@Override public IType getType() {
|
||||||
|
return new CPPQualifierType(type, isConst, isVolatile);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static ICPPFunction findOperator(IASTExpression exp, ICPPClassType cls) {
|
public static ICPPFunction findOperator(IASTExpression exp, ICPPClassType cls) {
|
||||||
IScope scope = null;
|
IScope scope = null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -939,24 +939,8 @@ public class CPPVisitor {
|
||||||
}
|
}
|
||||||
} else if (parent instanceof ICPPASTFieldReference) {
|
} else if (parent instanceof ICPPASTFieldReference) {
|
||||||
final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference)parent;
|
final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference)parent;
|
||||||
IASTExpression owner = fieldReference.getFieldOwner();
|
IType type = CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldReference);
|
||||||
IType type = getExpressionType(owner);
|
type= getUltimateType(type, false);
|
||||||
if (fieldReference.isPointerDereference()) {
|
|
||||||
// bug 205964: as long as the type is a class type, recurse.
|
|
||||||
// Be defensive and allow a max of 10 levels.
|
|
||||||
for (int j = 0; j < 10; j++) {
|
|
||||||
type= getUltimateTypeUptoPointers(type);
|
|
||||||
if (type instanceof ICPPClassType) {
|
|
||||||
ICPPFunction op = CPPSemantics.findOperator(fieldReference, (ICPPClassType) type);
|
|
||||||
if (op != null) {
|
|
||||||
type = op.getType().getReturnType();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type = getUltimateType(type, false);
|
|
||||||
if (type instanceof ICPPClassType) {
|
if (type instanceof ICPPClassType) {
|
||||||
return ((ICPPClassType) type).getCompositeScope();
|
return ((ICPPClassType) type).getCompositeScope();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDeferredClassInstance;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
|
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
@ -66,7 +67,9 @@ public class Conversions {
|
||||||
public static Cost checkImplicitConversionSequence(boolean allowUDC, IASTExpression sourceExp, IType source, IType target, boolean isImpliedObject) throws DOMException {
|
public static Cost checkImplicitConversionSequence(boolean allowUDC, IASTExpression sourceExp, IType source, IType target, boolean isImpliedObject) throws DOMException {
|
||||||
Cost cost;
|
Cost cost;
|
||||||
|
|
||||||
if (!isImpliedObject && target instanceof ICPPReferenceType) {
|
allowUDC &= !isImpliedObject;
|
||||||
|
|
||||||
|
if (target instanceof ICPPReferenceType) {
|
||||||
// [13.3.3.3.1] Reference binding
|
// [13.3.3.3.1] Reference binding
|
||||||
IType cv1T1= ((ICPPReferenceType)target).getType();
|
IType cv1T1= ((ICPPReferenceType)target).getType();
|
||||||
cost= new Cost(source, cv1T1);
|
cost= new Cost(source, cv1T1);
|
||||||
|
@ -79,6 +82,14 @@ public class Conversions {
|
||||||
/* Direct reference binding */
|
/* Direct reference binding */
|
||||||
// [13.3.3.1.4]
|
// [13.3.3.1.4]
|
||||||
|
|
||||||
|
if (cost.source.isSameType(cost.target) ||
|
||||||
|
// 7.3.3.13 for overload resolution the implicit this pointer is treated as if
|
||||||
|
// it were a pointer to the derived class
|
||||||
|
(isImpliedObject && cost.source instanceof ICPPClassType && cost.target instanceof ICPPClassType)) {
|
||||||
|
cost.rank = Cost.IDENTITY_RANK;
|
||||||
|
return cost;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
* is an lvalue (but is not a bit-field), and "cv1 T1" is reference-compatible with "cv2 T2,"
|
||||||
*/
|
*/
|
||||||
|
@ -87,43 +98,45 @@ public class Conversions {
|
||||||
qualificationConversion(cost);
|
qualificationConversion(cost);
|
||||||
|
|
||||||
derivedToBaseConversion(cost);
|
derivedToBaseConversion(cost);
|
||||||
} else if (T2 instanceof ICPPClassType && allowUDC) {
|
} else if (T2 instanceof ICPPClassType) {
|
||||||
/*
|
if(allowUDC) {
|
||||||
* or has a class type (i.e., T2 is a class type) and can be implicitly converted to
|
/*
|
||||||
* an lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible with "cv3 T3" 92)
|
* or has a class type (i.e., T2 is a class type) and can be implicitly converted to
|
||||||
* (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
* an lvalue of type "cv3 T3," where "cv1 T1" is reference-compatible with "cv3 T3" 92)
|
||||||
* and choosing the best one through overload resolution (13.3)).
|
* (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6)
|
||||||
*/
|
* and choosing the best one through overload resolution (13.3)).
|
||||||
ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType)T2);
|
*/
|
||||||
Cost operatorCost= null;
|
ICPPMethod[] fcns= SemanticUtil.getConversionOperators((ICPPClassType)T2);
|
||||||
ICPPMethod conv= null;
|
Cost operatorCost= null;
|
||||||
boolean ambiguousConversionOperator= false;
|
ICPPMethod conv= null;
|
||||||
if (fcns.length > 0 && fcns[0] instanceof IProblemBinding == false) {
|
boolean ambiguousConversionOperator= false;
|
||||||
for (final ICPPMethod op : fcns) {
|
if (fcns.length > 0 && fcns[0] instanceof IProblemBinding == false) {
|
||||||
Cost cost2 = checkStandardConversionSequence(op.getType().getReturnType(), target, false);
|
for (final ICPPMethod op : fcns) {
|
||||||
if (cost2.rank != Cost.NO_MATCH_RANK) {
|
Cost cost2 = checkStandardConversionSequence(op.getType().getReturnType(), target, false);
|
||||||
if (operatorCost == null) {
|
if (cost2.rank != Cost.NO_MATCH_RANK) {
|
||||||
operatorCost= cost2;
|
if (operatorCost == null) {
|
||||||
conv= op;
|
|
||||||
} else {
|
|
||||||
int cmp= operatorCost.compare(cost2);
|
|
||||||
if (cmp >= 0) {
|
|
||||||
ambiguousConversionOperator= cmp == 0;
|
|
||||||
operatorCost= cost2;
|
operatorCost= cost2;
|
||||||
conv= op;
|
conv= op;
|
||||||
|
} else {
|
||||||
|
int cmp= operatorCost.compare(cost2);
|
||||||
|
if (cmp >= 0) {
|
||||||
|
ambiguousConversionOperator= cmp == 0;
|
||||||
|
operatorCost= cost2;
|
||||||
|
conv= op;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (conv!= null && !ambiguousConversionOperator) {
|
if (conv!= null && !ambiguousConversionOperator) {
|
||||||
IType newSource= conv.getType().getReturnType();
|
IType newSource= conv.getType().getReturnType();
|
||||||
boolean isNewSourceLValue= newSource instanceof ICPPReferenceType;
|
boolean isNewSourceLValue= newSource instanceof ICPPReferenceType;
|
||||||
if (isNewSourceLValue && isReferenceCompatible(cv1T1, newSource)) {
|
if (isNewSourceLValue && isReferenceCompatible(cv1T1, newSource)) {
|
||||||
cost= new Cost(cv1T1, newSource);
|
cost= new Cost(cv1T1, newSource);
|
||||||
qualificationConversion(cost);
|
qualificationConversion(cost);
|
||||||
derivedToBaseConversion(cost);
|
derivedToBaseConversion(cost);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,8 +462,11 @@ public class Conversions {
|
||||||
|
|
||||||
if (maxdepth > 0 && type instanceof ICPPClassType && ancestorToFind instanceof ICPPClassType) {
|
if (maxdepth > 0 && type instanceof ICPPClassType && ancestorToFind instanceof ICPPClassType) {
|
||||||
ICPPClassType clazz = (ICPPClassType) type;
|
ICPPClassType clazz = (ICPPClassType) type;
|
||||||
ICPPBase[] bases= clazz.getBases();
|
if(clazz instanceof ICPPDeferredClassInstance) {
|
||||||
for (ICPPBase cppBase : bases) {
|
clazz= (ICPPClassType) ((ICPPDeferredClassInstance)clazz).getSpecializedBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ICPPBase cppBase : clazz.getBases()) {
|
||||||
IBinding base= cppBase.getBaseClass();
|
IBinding base= cppBase.getBaseClass();
|
||||||
if (base instanceof IType) {
|
if (base instanceof IType) {
|
||||||
IType tbase= (IType) base;
|
IType tbase= (IType) base;
|
||||||
|
|
|
@ -55,8 +55,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUnaryExpression;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
|
||||||
|
@ -334,18 +332,11 @@ class LookupData {
|
||||||
}
|
}
|
||||||
if (prop == IASTFieldReference.FIELD_NAME) {
|
if (prop == IASTFieldReference.FIELD_NAME) {
|
||||||
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempNameParent;
|
ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempNameParent;
|
||||||
IType implied = CPPVisitor.getExpressionType(fieldRef.getFieldOwner());
|
IType implied= CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldRef);
|
||||||
IType ultimateImplied= SemanticUtil.getUltimateTypeUptoPointers(implied);
|
implied= SemanticUtil.getUltimateTypeUptoPointers(implied);
|
||||||
if (fieldRef.isPointerDereference()) {
|
if (fieldRef.isPointerDereference() && implied instanceof IPointerType) {
|
||||||
if (ultimateImplied instanceof ICPPClassType) {
|
return ((IPointerType)implied).getType();
|
||||||
ICPPFunction operator= CPPSemantics.findOperator(fieldRef, (ICPPClassType) ultimateImplied);
|
}
|
||||||
if (operator!=null) {
|
|
||||||
return operator.getType().getReturnType();
|
|
||||||
}
|
|
||||||
} else if (implied instanceof IPointerType) {
|
|
||||||
return ((IPointerType)implied).getType();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return implied;
|
return implied;
|
||||||
}
|
}
|
||||||
if (prop == IASTIdExpression.ID_NAME) {
|
if (prop == IASTIdExpression.ID_NAME) {
|
||||||
|
|
|
@ -572,7 +572,7 @@ public class RenameRegressionTests extends RenameTests {
|
||||||
writer = new StringWriter();
|
writer = new StringWriter();
|
||||||
writer.write( "#include \"t.hh\" \n" ); //$NON-NLS-1$
|
writer.write( "#include \"t.hh\" \n" ); //$NON-NLS-1$
|
||||||
writer.write( "void test() { \n" ); //$NON-NLS-1$
|
writer.write( "void test() { \n" ); //$NON-NLS-1$
|
||||||
writer.write( " Foo d; \n" ); //$NON-NLS-1$
|
writer.write( " Foo* d; \n" ); //$NON-NLS-1$
|
||||||
writer.write( " d->method1(1); \n" ); //$NON-NLS-1$
|
writer.write( " d->method1(1); \n" ); //$NON-NLS-1$
|
||||||
writer.write( "} \n" ); //$NON-NLS-1$
|
writer.write( "} \n" ); //$NON-NLS-1$
|
||||||
String source = writer.toString();
|
String source = writer.toString();
|
||||||
|
|
Loading…
Add table
Reference in a new issue