diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 98fa2ea91e0..bad33dca9c0 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -5795,4 +5795,120 @@ public class AST2CPPTests extends AST2BaseTest { ICPPFunction fn2= bh.assertNonProblem("func(&C::m2", 4, ICPPFunction.class); 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); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 46ce31dbf4a..30fda240df4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -2970,4 +2970,54 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPSpecialization ctps= ba.assertNonProblem("C", 7, ICPPSpecialization.class, ICPPClassType.class); assertFalse(ctps instanceof ICPPTemplateInstance); } + + // class A { + // public: + // A(const A& a) {} + // }; + // + // template + // class B : A { + // public: + // B(const B& 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 + // class C : public B { + // public: + // void foo(T *t) { + // B::foo(static_cast(t)); + // } + // }; + public void testMemberLookupThroughDeferredClassBase() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ba.assertNonProblem("foo(s", 3); + } + + // template + // class A { + // public: + // inline int foo() const; + // inline int bar() const; + // }; + // + // template + // inline int A::bar() const { + // return foo(); + // } + public void testMemberReferenceFromTemplatedMethodDefinition_238232() throws Exception { + BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), true); + ba.assertNonProblem("foo();", 3); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java index 5fa38091420..ddb506d73a1 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java @@ -1275,7 +1275,7 @@ public class CompleteParser2Tests extends BaseTestCase { buff.append( " void f_SD_01(); \n"); //$NON-NLS-1$ buff.append( "}; \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( "} \n"); //$NON-NLS-1$ buff.append( "void SD_01::f_SD_01() \n"); //$NON-NLS-1$ // REFERENCE SD_01 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 379c4e8fc9d..16e1e7868b4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -15,6 +15,7 @@ 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.getUltimateTypeUptoPointers; import java.util.ArrayList; 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.IFunctionType; 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.IQualifierType; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IType; 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.ASTNode; 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.CPPASTTranslationUnit; 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.CPPUsingDeclaration; 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.ICPPInternalTemplateInstantiator; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; @@ -2372,6 +2378,80 @@ public class CPPSemantics { } return result; } + + /** + * For a pointer dereference expression e1->e2, return the type that e1 ultimately evaluates to + * when chaining overloaded class member access operators operator->() calls. + * @param fieldReference + * @return the type the field owner expression ultimately evaluates to when chaining overloaded + * class member access operators operator->() 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) { IScope scope = null; try { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index d4526456ba4..4aa32ecfd74 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -939,24 +939,8 @@ public class CPPVisitor { } } else if (parent instanceof ICPPASTFieldReference) { final ICPPASTFieldReference fieldReference = (ICPPASTFieldReference)parent; - IASTExpression owner = fieldReference.getFieldOwner(); - IType type = getExpressionType(owner); - 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); + IType type = CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldReference); + type= getUltimateType(type, false); if (type instanceof ICPPClassType) { return ((ICPPClassType) type).getCompositeScope(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 94e9edaceea..c9af08f157e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -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.internal.core.dom.parser.ITypeContainer; 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.index.IIndexFragmentBinding; 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 { Cost cost; - if (!isImpliedObject && target instanceof ICPPReferenceType) { + allowUDC &= !isImpliedObject; + + if (target instanceof ICPPReferenceType) { // [13.3.3.3.1] Reference binding IType cv1T1= ((ICPPReferenceType)target).getType(); cost= new Cost(source, cv1T1); @@ -79,6 +82,14 @@ public class Conversions { /* Direct reference binding */ // [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," */ @@ -87,43 +98,45 @@ public class Conversions { qualificationConversion(cost); derivedToBaseConversion(cost); - } else if (T2 instanceof ICPPClassType && 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) - * (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 conv= null; - boolean ambiguousConversionOperator= false; - if (fcns.length > 0 && fcns[0] instanceof IProblemBinding == false) { - for (final ICPPMethod op : fcns) { - Cost cost2 = checkStandardConversionSequence(op.getType().getReturnType(), target, false); - if (cost2.rank != Cost.NO_MATCH_RANK) { - if (operatorCost == null) { - operatorCost= cost2; - conv= op; - } else { - int cmp= operatorCost.compare(cost2); - if (cmp >= 0) { - ambiguousConversionOperator= cmp == 0; + } 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) + * (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 conv= null; + boolean ambiguousConversionOperator= false; + if (fcns.length > 0 && fcns[0] instanceof IProblemBinding == false) { + for (final ICPPMethod op : fcns) { + Cost cost2 = checkStandardConversionSequence(op.getType().getReturnType(), target, false); + if (cost2.rank != Cost.NO_MATCH_RANK) { + if (operatorCost == null) { operatorCost= cost2; conv= op; + } else { + int cmp= operatorCost.compare(cost2); + if (cmp >= 0) { + ambiguousConversionOperator= cmp == 0; + operatorCost= cost2; + conv= op; + } } } } } - } - if (conv!= null && !ambiguousConversionOperator) { - IType newSource= conv.getType().getReturnType(); - boolean isNewSourceLValue= newSource instanceof ICPPReferenceType; - if (isNewSourceLValue && isReferenceCompatible(cv1T1, newSource)) { - cost= new Cost(cv1T1, newSource); - qualificationConversion(cost); - derivedToBaseConversion(cost); + if (conv!= null && !ambiguousConversionOperator) { + IType newSource= conv.getType().getReturnType(); + boolean isNewSourceLValue= newSource instanceof ICPPReferenceType; + if (isNewSourceLValue && isReferenceCompatible(cv1T1, newSource)) { + cost= new Cost(cv1T1, newSource); + qualificationConversion(cost); + derivedToBaseConversion(cost); + } } } } @@ -449,8 +462,11 @@ public class Conversions { if (maxdepth > 0 && type instanceof ICPPClassType && ancestorToFind instanceof ICPPClassType) { ICPPClassType clazz = (ICPPClassType) type; - ICPPBase[] bases= clazz.getBases(); - for (ICPPBase cppBase : bases) { + if(clazz instanceof ICPPDeferredClassInstance) { + clazz= (ICPPClassType) ((ICPPDeferredClassInstance)clazz).getSpecializedBinding(); + } + + for (ICPPBase cppBase : clazz.getBases()) { IBinding base= cppBase.getBaseClass(); if (base instanceof IType) { IType tbase= (IType) base; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java index 437d2a30309..60823145b59 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/LookupData.java @@ -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.ICPPASTUsingDirective; 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.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; @@ -334,18 +332,11 @@ class LookupData { } if (prop == IASTFieldReference.FIELD_NAME) { ICPPASTFieldReference fieldRef = (ICPPASTFieldReference) tempNameParent; - IType implied = CPPVisitor.getExpressionType(fieldRef.getFieldOwner()); - IType ultimateImplied= SemanticUtil.getUltimateTypeUptoPointers(implied); - if (fieldRef.isPointerDereference()) { - if (ultimateImplied instanceof ICPPClassType) { - ICPPFunction operator= CPPSemantics.findOperator(fieldRef, (ICPPClassType) ultimateImplied); - if (operator!=null) { - return operator.getType().getReturnType(); - } - } else if (implied instanceof IPointerType) { - return ((IPointerType)implied).getType(); - } - } + IType implied= CPPSemantics.getChainedMemberAccessOperatorReturnType(fieldRef); + implied= SemanticUtil.getUltimateTypeUptoPointers(implied); + if (fieldRef.isPointerDereference() && implied instanceof IPointerType) { + return ((IPointerType)implied).getType(); + } return implied; } if (prop == IASTIdExpression.ID_NAME) { diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java index d5112a1a3d7..f3d7eedfdf8 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/refactoring/rename/RenameRegressionTests.java @@ -572,7 +572,7 @@ public class RenameRegressionTests extends RenameTests { writer = new StringWriter(); writer.write( "#include \"t.hh\" \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( "} \n" ); //$NON-NLS-1$ String source = writer.toString();