1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

more c++ pointers to members

This commit is contained in:
Andrew Niefer 2005-02-15 19:50:13 +00:00
parent c20e7686d9
commit 87ca6fed25
5 changed files with 214 additions and 61 deletions

View file

@ -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 );
}
}

View file

@ -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();
}

View file

@ -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();

View file

@ -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;
}

View file

@ -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 )
{