From 87ca6fed25c06a3bd94f4e5063da1c409719e4c3 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Tue, 15 Feb 2005 19:50:13 +0000 Subject: [PATCH] more c++ pointers to members --- .../core/parser/tests/ast2/AST2CPPTests.java | 89 ++++++++++++- .../dom/ast/cpp/ICPPPointerToMemberType.java | 3 +- .../parser/cpp/CPPPointerToMemberType.java | 38 +++++- .../core/dom/parser/cpp/CPPSemantics.java | 122 +++++++++++------- .../core/dom/parser/cpp/CPPVisitor.java | 23 +++- 5 files changed, 214 insertions(+), 61 deletions(-) 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 27e3d304e4e..d7fb756da90 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 @@ -1500,7 +1500,7 @@ public class AST2CPPTests extends AST2BaseTest { IType t = pm.getType(); assertNotNull(t); assertTrue(t instanceof ICPPPointerToMemberType); - ICPPClassType cls = ((ICPPPointerToMemberType) t).getMemberOfClass(); + ICPPClassType cls = (ICPPClassType) ((ICPPPointerToMemberType) t).getMemberOfClass(); assertSame(S, cls); assertTrue(((ICPPPointerToMemberType) t).getType() instanceof IBasicType); } @@ -1547,7 +1547,7 @@ public class AST2CPPTests extends AST2BaseTest { assertTrue(t instanceof ICPPPointerToMemberType); IFunctionType ft = (IFunctionType) ((ICPPPointerToMemberType) t) .getType(); - ICPPClassType ST = ((ICPPPointerToMemberType) t) + ICPPClassType ST = (ICPPClassType) ((ICPPPointerToMemberType) t) .getMemberOfClass(); assertTrue(ft.getReturnType() instanceof IPointerType); @@ -1619,5 +1619,90 @@ public class AST2CPPTests extends AST2BaseTest { // assertTrue( body.getStatements()[0] instanceof IASTDeclarationStatement ); // } + + public void testPMConversions() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class A { public: int i; }; \n"); //$NON-NLS-1$ + buffer.append("class B : public A {}; \n"); //$NON-NLS-1$ + buffer.append("void f( int B::* ); \n"); //$NON-NLS-1$ + buffer.append("void g() { \n"); //$NON-NLS-1$ + buffer.append(" int A::* pm = &A::i; \n"); //$NON-NLS-1$ + buffer.append(" f( pm ); \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + IFunction f = (IFunction) col.getName(15).resolveBinding(); + ICPPClassType A = (ICPPClassType) col.getName(0).resolveBinding(); + ICPPField i = (ICPPField) col.getName(1).resolveBinding(); + ICPPClassType B = (ICPPClassType) col.getName(2).resolveBinding(); + IVariable pm = (IVariable) col.getName(11).resolveBinding(); + + assertInstances( col, f, 2 ); + assertInstances( col, A, 4 ); + assertInstances( col, i, 3 ); + assertInstances( col, B, 2 ); + assertInstances( col, pm, 2 ); + } + + public void testPMKoenig() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "namespace N { \n" ); //$NON-NLS-1$ + buffer.append( " class A { public: int i; }; \n" ); //$NON-NLS-1$ + buffer.append( " void f( int A::* ); \n" ); //$NON-NLS-1$ + buffer.append( "} \n" ); //$NON-NLS-1$ + buffer.append( "int N::A::* pm = &N::A::i; \n" ); //$NON-NLS-1$ + buffer.append( "void g() { \n" ); //$NON-NLS-1$ + buffer.append( " f( pm ); \n" ); //$NON-NLS-1$ + buffer.append( "} \n" ); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + IFunction f = (IFunction) col.getName(16).resolveBinding(); + ICPPNamespace N = (ICPPNamespace) col.getName(0).resolveBinding(); + ICPPClassType A = (ICPPClassType) col.getName(1).resolveBinding(); + + assertInstances( col, f, 2 ); + assertInstances( col, N, 3 ); + assertInstances( col, A, 4 ); + } + + public void testPMKoenig_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "namespace M { \n" ); //$NON-NLS-1$ + buffer.append( " class B { }; \n" ); //$NON-NLS-1$ + buffer.append( " void f( B* ); \n" ); //$NON-NLS-1$ + buffer.append( "} \n" ); //$NON-NLS-1$ + buffer.append( "namespace N { \n" ); //$NON-NLS-1$ + buffer.append( " class A { public: M::B * b; }; \n" ); //$NON-NLS-1$ + buffer.append( "} \n" ); //$NON-NLS-1$ + buffer.append( "M::B* N::A::* pm = &N::A::b; \n" ); //$NON-NLS-1$ + buffer.append( "void g() { \n" ); //$NON-NLS-1$ + buffer.append( " N::A * a; \n" ); //$NON-NLS-1$ + buffer.append( " f( a->*pm ); \n" ); //$NON-NLS-1$ + buffer.append( "} \n" ); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + IFunction f = (IFunction) col.getName(27).resolveBinding(); + ICPPNamespace M = (ICPPNamespace) col.getName(0).resolveBinding(); + ICPPClassType B = (ICPPClassType) col.getName(1).resolveBinding(); + ICPPNamespace N = (ICPPNamespace) col.getName(5).resolveBinding(); + ICPPClassType A = (ICPPClassType) col.getName(6).resolveBinding(); + IVariable pm = (IVariable) col.getName(17).resolveBinding(); + + assertInstances( col, f, 2 ); + assertInstances( col, M, 3 ); + assertInstances( col, B, 6 ); + assertInstances( col, N, 4 ); + assertInstances( col, A, 5 ); + assertInstances( col, pm, 2 ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPPointerToMemberType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPPointerToMemberType.java index 98390f97d3c..d0c459cdab9 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPPointerToMemberType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPPointerToMemberType.java @@ -14,11 +14,12 @@ */ package org.eclipse.cdt.core.dom.ast.cpp; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IPointerType; /** * @author aniefer */ public interface ICPPPointerToMemberType extends IPointerType { - public ICPPClassType getMemberOfClass(); + public IBinding getMemberOfClass(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerToMemberType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerToMemberType.java index 5f4cf56d0e0..12a8f74f08e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerToMemberType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerToMemberType.java @@ -1,8 +1,15 @@ +/********************************************************************** + * Copyright (c) 2005 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v10.html + * + * Contributors: + * IBM - Initial API and implementation + **********************************************************************/ /* * Created on Feb 11, 2005 - * - * TODO To change the template for this generated file go to - * Window - Preferences - Java - Code Style - Code Templates */ package org.eclipse.cdt.internal.core.dom.parser.cpp; @@ -10,6 +17,7 @@ import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; @@ -17,9 +25,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; /** * @author aniefer - * - * TODO To change the template for this generated type comment go to - * Window - Preferences - Java - Code Style - Code Templates */ public class CPPPointerToMemberType extends CPPPointerType implements ICPPPointerToMemberType { @@ -33,10 +38,29 @@ public class CPPPointerToMemberType extends CPPPointerType implements super(type, operator); } + public boolean equals( Object o ){ + if( !super.equals( o ) ) + return false; + + if( !( o instanceof CPPPointerToMemberType ) ) + return false; + + + if( o instanceof ITypedef ) + return o.equals( this ); + + + CPPPointerToMemberType pt = (CPPPointerToMemberType) o; + IBinding cls = pt.getMemberOfClass(); + if( cls != null ) + return cls.equals( getMemberOfClass() ); + return false; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType#getMemberOfClass() */ - public ICPPClassType getMemberOfClass() { + public IBinding getMemberOfClass() { if( clsType == null ){ ICPPASTPointerToMember pm = (ICPPASTPointerToMember) operator; IASTName name = pm.getName(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 69edb6ab1b1..4e9c5856df0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -76,6 +76,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; @@ -465,7 +466,7 @@ public class CPPSemantics { ObjectSet classes = new ObjectSet(2); for( int i = 0; i < ps.length; i++ ){ IType p = getSourceParameterType( ps, i ); - p = getUltimateType( p ); + p = getUltimateType( p, true ); try { getAssociatedScopes( p, namespaces, classes ); } catch ( DOMException e ) { @@ -492,11 +493,16 @@ public class CPPSemantics { } else if( t instanceof IFunctionType ){ IFunctionType ft = (IFunctionType) t; - getAssociatedScopes( getUltimateType( ft.getReturnType() ), namespaces, classes ); + getAssociatedScopes( getUltimateType( ft.getReturnType(), true ), namespaces, classes ); IType [] ps = ft.getParameterTypes(); for( int i = 0; i < ps.length; i++ ){ - getAssociatedScopes( getUltimateType( ps[i] ), namespaces, classes ); + getAssociatedScopes( getUltimateType( ps[i], true ), namespaces, classes ); } + } else if( t instanceof ICPPPointerToMemberType ){ + IBinding binding = ((ICPPPointerToMemberType)t).getMemberOfClass(); + if( binding instanceof IType ) + getAssociatedScopes( (IType)binding, namespaces, classes ); + getAssociatedScopes( getUltimateType( ((ICPPPointerToMemberType)t).getType(), true ), namespaces, classes ); } return; } @@ -1413,8 +1419,8 @@ public class CPPSemantics { } //was the qualification conversion enough? - IType s = getUltimateType( cost.source ); - IType t = getUltimateType( cost.target ); + IType s = getUltimateType( cost.source, true ); + IType t = getUltimateType( cost.target, true ); if( s.equals( t ) ){ return cost; } @@ -1439,8 +1445,8 @@ public class CPPSemantics { Cost constructorCost = null; Cost conversionCost = null; - IType s = getUltimateType( source ); - IType t = getUltimateType( target ); + IType s = getUltimateType( source, true ); + IType t = getUltimateType( target, true ); ICPPConstructor constructor = null; ICPPMethod conversion = null; @@ -1453,7 +1459,9 @@ public class CPPSemantics { ICPPConstructor [] constructors = ((ICPPClassType)t).getConstructors(); if( constructors.length > 0 ){ - constructor = (ICPPConstructor) resolveFunction( data, Arrays.asList( constructors ) ); + //the list out of Arrays.asList does not support remove, which we need + ArrayList list = new ArrayList( Arrays.asList( constructors ) ); + constructor = (ICPPConstructor) resolveFunction( data, list ); } if( constructor != null && constructor.isExplicit() ){ constructor = null; @@ -1503,13 +1511,15 @@ public class CPPSemantics { return cost; } - static protected IType getUltimateType( IType type ){ + static protected IType getUltimateType( IType type, boolean stopAtPointerToMember ){ try { while( true ){ if( type instanceof ITypedef ) type = ((ITypedef)type).getType(); else if( type instanceof IQualifierType ) type = ((IQualifierType)type).getType(); + else if( stopAtPointerToMember && type instanceof ICPPPointerToMemberType ) + return type; else if( type instanceof IPointerType ) type = ((IPointerType) type).getType(); else if( type instanceof ICPPReferenceType ) @@ -1523,7 +1533,7 @@ public class CPPSemantics { } static private boolean isCompleteType( IType type ){ - type = getUltimateType( type ); + type = getUltimateType( type, false ); if( type instanceof ICPPClassType && ((ICPPBinding)type).getDefinition() == null ){ return false; } @@ -1583,7 +1593,10 @@ public class CPPSemantics { else if( op1 == null ^ op2 == null) { canConvert = false; break; - } + } else if( op1 instanceof ICPPPointerToMemberType ^ op2 instanceof ICPPPointerToMemberType ){ + canConvert = false; + break; + } //if const is in cv1,j then const is in cv2,j. Similary for volatile if( ( op1.isConst() && !op2.isConst() ) || ( op1.isVolatile() && !op2.isVolatile() ) ) { @@ -1634,8 +1647,8 @@ public class CPPSemantics { * @throws DOMException */ static private void promotion( Cost cost ) throws DOMException{ - IType src = getUltimateType( cost.source ); - IType trg = getUltimateType( cost.target ); + IType src = getUltimateType( cost.source, true ); + IType trg = getUltimateType( cost.target, true ); if( src.equals( trg ) ) return; @@ -1666,15 +1679,10 @@ public class CPPSemantics { cost.conversion = 0; cost.detail = 0; - -// if( !src.hasSamePtrs( trg ) ){ -// return; -// } -// - IType s = getUltimateType( src ); - IType t = getUltimateType( trg ); - - + + IType s = getUltimateType( src, true ); + IType t = getUltimateType( trg, true ); + if( s instanceof ICPPClassType ){ //4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be //converted to an rvalue of type "pointer to cv void" @@ -1698,32 +1706,24 @@ public class CPPSemantics { //An rvalue of an enumeration type can be converted to an rvalue of an integer type. cost.rank = Cost.CONVERSION_RANK; cost.conversion = 1; - } - - //TODO -// else if( ptr.getType() == ITypeInfo.PtrOp.t_memberPointer ){ -// //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type, -// //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a -// //derived class of B -// ITypeInfo.PtrOp srcPtr = trg.hasPtrOperators() ? (ITypeInfo.PtrOp)trg.getPtrOperators().get(0) : null; -// if( trgDecl.isType( srcDecl.getType() ) && srcPtr != null && srcPtr.getType() == ITypeInfo.PtrOp.t_memberPointer ){ -// try { -// temp = hasBaseClass( ptr.getMemberOf(), srcPtr.getMemberOf() ); -// } catch (ParserSymbolTableException e) { -// //not going to happen since we didn't ask for the visibility exception -// } -// cost.rank = ( temp > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK; -// cost.detail = 1; -// cost.conversion = ( temp > -1 ) ? temp : 0; -// return; -// } -// } - + } else if( s instanceof ICPPPointerToMemberType && t instanceof ICPPPointerToMemberType ){ + //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type, + //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a + //derived class of B + ICPPPointerToMemberType spm = (ICPPPointerToMemberType) s; + ICPPPointerToMemberType tpm = (ICPPPointerToMemberType) t; + if( spm.getType().equals( tpm.getType() ) ){ + temp = hasBaseClass( tpm.getMemberOfClass(), spm.getMemberOfClass(), false ); + cost.rank = ( temp > -1 ) ? Cost.CONVERSION_RANK : Cost.NO_MATCH_RANK; + cost.conversion = ( temp > -1 ) ? temp : 0; + cost.detail = 1; + } + } } static private void derivedToBaseConversion( Cost cost ) throws DOMException { - IType s = getUltimateType( cost.source ); - IType t = getUltimateType( cost.target ); + IType s = getUltimateType( cost.source, true ); + IType t = getUltimateType( cost.target, true ); if( cost.targetHadReference && s instanceof ICPPClassType && t instanceof ICPPClassType ){ int temp = hasBaseClass( (ICPPClassType) s, (ICPPClassType) t, true ); @@ -1735,24 +1735,48 @@ public class CPPSemantics { } } - static private int hasBaseClass( ICPPClassType symbol, ICPPClassType base, boolean needVisibility ) throws DOMException { + static private int hasBaseClass( IBinding symbol, IBinding base, boolean needVisibility ) throws DOMException { if( symbol == base ){ return 0; } + ICPPClassType clsSymbol = null; + ICPPClassType clsBase = null; + IType temp = null; + while( symbol instanceof ITypedef ){ + temp = ((ITypedef)symbol).getType(); + if( temp instanceof IBinding ) + symbol = (IBinding) temp; + else return -1; + } + if( symbol instanceof ICPPClassType ) + clsSymbol = (ICPPClassType) symbol; + else return -1; + + while( base instanceof ITypedef ){ + temp = ((ITypedef)base).getType(); + if( temp instanceof IBinding ) + base= (IBinding) temp; + else return -1; + } + if( base instanceof ICPPClassType ) + clsBase = (ICPPClassType) base; + else return -1; + + ICPPClassType parent = null; - ICPPBase [] bases = symbol.getBases(); + ICPPBase [] bases = clsSymbol.getBases(); for( int i = 0; i < bases.length; i ++ ){ ICPPBase wrapper = bases[i]; parent = bases[i].getBaseClass(); boolean isVisible = ( wrapper.getVisibility() == ICPPBase.v_public); - if( parent == base ){ + if( parent == clsBase ){ if( needVisibility && !isVisible ) return -1; return 1; } - int n = hasBaseClass( parent, base, needVisibility ); + int n = hasBaseClass( parent, clsBase, needVisibility ); if( n > 0 ) return n + 1; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index f3309d692b4..7b2bbe563b0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -88,6 +88,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; @@ -122,12 +123,14 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.IGNUASTCompoundStatementExpression; import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPASTSimpleDeclSpecifier; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; +import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; /** * @author aniefer @@ -537,7 +540,7 @@ public class CPPVisitor { } } else if( parent instanceof ICPPASTFieldReference ){ IASTExpression owner = ((ICPPASTFieldReference)parent).getFieldOwner(); - IType type = CPPSemantics.getUltimateType( getExpressionType( owner ) ); + IType type = CPPSemantics.getUltimateType( getExpressionType( owner ), false ); if( type instanceof ICPPClassType ){ return ((ICPPClassType) type).getCompositeScope(); } @@ -1571,7 +1574,7 @@ public class CPPVisitor { private static IType getPointerTypes( IType type, IASTDeclarator declarator ){ IASTPointerOperator [] ptrOps = declarator.getPointerOperators(); - for( int i = ptrOps.length - 1; i >= 0; i-- ){ + for( int i = 0; i < ptrOps.length; i++ ){ if( ptrOps[i] instanceof ICPPASTPointerToMember ) type = new CPPPointerToMemberType( type, (ICPPASTPointerToMember) ptrOps[i] ); else if( ptrOps[i] instanceof IASTPointer ) @@ -1751,6 +1754,22 @@ public class CPPVisitor { return e.getProblem(); } } + } else if( expression instanceof IASTBinaryExpression ){ + IASTBinaryExpression binary = (IASTBinaryExpression) expression; + IType type = getExpressionType( ((IASTBinaryExpression) expression).getOperand2() ); + if( binary.getOperator() == ICPPASTBinaryExpression.op_pmarrow || + binary.getOperator() == ICPPASTBinaryExpression.op_pmdot ) + { + if( type instanceof ICPPPointerToMemberType ){ + try { + return ((ICPPPointerToMemberType)type).getType(); + } catch ( DOMException e ) { + return e.getProblem(); + } + } + return new ProblemBinding( IProblemBinding.SEMANTIC_INVALID_TYPE, new char[0] ); + } + return type; } else if( expression instanceof IASTUnaryExpression ) {