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 651ee9f60b0..824d63dbed3 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 @@ -51,6 +51,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; 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.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.ParserLanguage; @@ -1439,5 +1440,76 @@ public class AST2CPPTests extends AST2BaseTest { assertEquals( 9, col.size() ); } + + public void testPointerToMemberType() throws Exception { + IASTTranslationUnit tu = parse( "struct S; int S::* pm;", ParserLanguage.CPP ); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit(tu, col); + + assertEquals( 4, col.size() ); + + IVariable pm = (IVariable) col.getName(3).resolveBinding(); + ICPPClassType S = (ICPPClassType) col.getName(0).resolveBinding(); + + IType t = pm.getType(); + assertNotNull( t ); + assertTrue( t instanceof ICPPPointerToMemberType ); + ICPPClassType cls = ((ICPPPointerToMemberType)t).getMemberOfClass(); + assertSame( S, cls ); + assertTrue( ((ICPPPointerToMemberType)t).getType() instanceof IBasicType ); + } + + public void testBug_PM_() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("struct S { int i ; } *s; \n"); //$NON-NLS-1$ + buffer.append("int S::* pm = &S::i; \n"); //$NON-NLS-1$ + buffer.append("void f() { \n"); //$NON-NLS-1$ + buffer.append(" s->*pm = 1; \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); + + IBinding ref = col.getName(11).resolveBinding(); + IVariable pm = (IVariable) col.getName(5).resolveBinding(); + + assertSame( pm, ref ); + } + + public void testBug_PM_2() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("struct S { \n"); //$NON-NLS-1$ + buffer.append(" int i; \n"); //$NON-NLS-1$ + buffer.append(" S* f(); \n"); //$NON-NLS-1$ + buffer.append("} *s; \n"); //$NON-NLS-1$ + buffer.append("S* (S::* pm) () = &S::f; \n"); //$NON-NLS-1$ + buffer.append("void foo() { \n"); //$NON-NLS-1$ + buffer.append(" (s->*pm)()->i; \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); + + ICPPClassType S = (ICPPClassType) col.getName(0).resolveBinding(); + IVariable pm = (IVariable) col.getName(8).resolveBinding(); + IField i = (IField) col.getName(1).resolveBinding(); + ICPPMethod f = (ICPPMethod) col.getName(3).resolveBinding(); + + IType t = pm.getType(); + assertTrue( t instanceof ICPPPointerToMemberType ); + IFunctionType ft = (IFunctionType) ((ICPPPointerToMemberType)t).getType(); + ICPPClassType ST = (ICPPClassType) ((ICPPPointerToMemberType)t).getMemberOfClass(); + + assertTrue( ft.getReturnType() instanceof IPointerType ); + assertSame( ST, ((IPointerType)ft.getReturnType()).getType() ); + assertSame( S, ST ); + + assertInstances(col, S, 5); + assertInstances(col, pm, 2); + assertInstances(col, i, 2); + assertInstances(col, f, 3); + } } 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 d0c459cdab9..98390f97d3c 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,12 +14,11 @@ */ 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 IBinding getMemberOfClass(); + public ICPPClassType getMemberOfClass(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java index d4b244681c8..7b4142f3c33 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTBinaryExpression.java @@ -10,14 +10,14 @@ **********************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression; import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTBinaryExpression; /** * @author jcamelon */ public class CPPASTBinaryExpression extends CPPASTNode implements - IASTBinaryExpression { + ICPPASTBinaryExpression { private int op; private IASTExpression operand1; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 5a551b13101..04b4d58b0a2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import java.util.List; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; @@ -40,11 +41,55 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.parser.util.CharArrayUtils; +import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; /** * @author aniefer */ public class CPPClassType implements ICPPClassType, ICPPBinding { + public static class CPPClassTypeProblem extends ProblemBinding implements ICPPClassType{ + public CPPClassTypeProblem( int id, char[] arg ) { + super( id, arg ); + } + + public ICPPBase[] getBases() throws DOMException { + throw new DOMException( this ); + } + public IField[] getFields() throws DOMException { + throw new DOMException( this ); + } + public List getDeclaredFields() throws DOMException { + throw new DOMException( this ); + } + public List getMethods() throws DOMException { + throw new DOMException( this ); + } + public List getAllDeclaredMethods() throws DOMException { + throw new DOMException( this ); + } + public List getDeclaredMethods() throws DOMException { + throw new DOMException( this ); + } + public ICPPConstructor[] getConstructors() throws DOMException { + throw new DOMException( this ); + } + public int getKey() throws DOMException { + throw new DOMException( this ); + } + public IField findField(String name) throws DOMException { + throw new DOMException( this ); + } + public IScope getCompositeScope() throws DOMException { + throw new DOMException( this ); + } + public IScope getParent() throws DOMException { + throw new DOMException( this ); + } + public List find(String name) throws DOMException { + throw new DOMException( this ); + } + } + private ICPPASTCompositeTypeSpecifier definition; private ICPPASTElaboratedTypeSpecifier [] declarations; 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 new file mode 100644 index 00000000000..5f4cf56d0e0 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerToMemberType.java @@ -0,0 +1,61 @@ +/* + * 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; + +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.cpp.ICPPASTPointerToMember; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +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 { + + private ICPPClassType clsType = null; + /** + * @param type + * @param operator + */ + public CPPPointerToMemberType(IType type, ICPPASTPointerToMember operator) { + super(type, operator); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType#getMemberOfClass() + */ + public ICPPClassType getMemberOfClass() { + if( clsType == null ){ + ICPPASTPointerToMember pm = (ICPPASTPointerToMember) operator; + IASTName name = pm.getName(); + if( name instanceof ICPPASTQualifiedName ){ + IASTName [] ns = ((ICPPASTQualifiedName)name).getNames(); + if( ns.length > 1 ) + name = ns[ ns.length - 2 ]; + else + name = ns[ ns.length - 1 ]; + } + + IBinding binding = name.resolveBinding(); + if( binding instanceof ICPPClassType ){ + clsType = (ICPPClassType) binding; + } else { + clsType = new CPPClassType.CPPClassTypeProblem( IProblemBinding.SEMANTIC_INVALID_TYPE, name.toCharArray() ); + } + } + return clsType; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerType.java index ef88ed1ab7e..4863914261b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPPointerType.java @@ -23,8 +23,8 @@ import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; * @author aniefer */ public class CPPPointerType implements IPointerType, ITypeContainer { - private IASTPointer operator = null; - private IType type = null; + protected IASTPointer operator = null; + protected IType type = null; /** * @param type * @param operator 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 b6b942c3ef8..d9e28d5ed01 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 @@ -470,41 +470,50 @@ public class CPPVisitor { public static IScope getContainingScope( IASTNode node ){ if( node == null ) return null; - if( node instanceof IASTName ) - return getContainingScope( (IASTName) node ); - else if( node instanceof IASTDeclaration ) - return getContainingScope( (IASTDeclaration) node ); - else if( node instanceof IASTStatement ) - return getContainingScope( (IASTStatement) node ); - else if( node instanceof IASTDeclSpecifier ) - return getContainingScope( (IASTDeclSpecifier) node ); - else if( node instanceof IASTParameterDeclaration ) - return getContainingScope( (IASTParameterDeclaration) node ); - else if( node instanceof IASTExpression ) - return getContainingScope( (IASTExpression) node ); - else if( node instanceof IASTEnumerator ){ - //put the enumerators in the same scope as the enumeration - return getContainingScope( (IASTEnumerationSpecifier) node.getParent() ); - } - - return getContainingScope( node.getParent() ); + while( node != null ){ + if( node instanceof IASTName ){ + return getContainingScope( (IASTName) node ); + } else if( node instanceof IASTDeclaration ){ + IASTNode parent = node.getParent(); + if( parent instanceof IASTTranslationUnit ){ + return ((IASTTranslationUnit)parent).getScope(); + } else if( parent instanceof IASTDeclarationStatement ){ + return getContainingScope( (IASTStatement) parent ); + } else if( parent instanceof IASTForStatement ){ + return ((IASTForStatement)parent).getScope(); + } else if( parent instanceof IASTCompositeTypeSpecifier ){ + return ((IASTCompositeTypeSpecifier)parent).getScope(); + } else if( parent instanceof ICPPASTNamespaceDefinition ) { + return ((ICPPASTNamespaceDefinition)parent).getScope(); + } + } else if( node instanceof IASTStatement ){ + return getContainingScope( (IASTStatement) node ); + } else if( node instanceof IASTTypeId ){ + node = node.getParent(); + } else if( node instanceof IASTParameterDeclaration ){ + ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) node.getParent(); + ASTNodeProperty prop = dtor.getPropertyInParent(); + if( prop == IASTSimpleDeclaration.DECLARATOR || prop == IASTFunctionDefinition.DECLARATOR ) + return dtor.getFunctionScope(); + } else if( node instanceof IASTExpression ){ + IASTNode parent = node.getParent(); + if( parent instanceof IASTForStatement ){ + return ((IASTForStatement)parent).getScope(); + } else if( parent instanceof IASTCompoundStatement ){ + return ((IASTCompoundStatement)parent).getScope(); + } else if( parent instanceof ICPPASTConstructorChainInitializer ){ + IASTNode temp = getContainingBlockItem( parent.getParent() ); + if( temp instanceof IASTFunctionDefinition ){ + IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition)temp).getBody(); + return body.getScope(); + } + } + } + node = node.getParent(); + } + return null; } - public static IScope getContainingScope( IASTExpression expression ){ - IASTNode parent = expression.getParent(); - if( parent instanceof IASTForStatement ){ - return ((IASTForStatement)parent).getScope(); - } else if( parent instanceof IASTCompoundStatement ){ - return ((IASTCompoundStatement)parent).getScope(); - } else if( parent instanceof ICPPASTConstructorChainInitializer ){ - IASTNode node = getContainingBlockItem( parent.getParent() ); - if( node instanceof IASTFunctionDefinition ){ - IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition)node).getBody(); - return body.getScope(); - } - } - return getContainingScope( parent ); - } public static IScope getContainingScope( IASTName name ){ IASTNode parent = name.getParent(); try { @@ -538,27 +547,7 @@ public class CPPVisitor { } return getContainingScope( parent ); } - /** - * @param declaration - * @return - */ - public static IScope getContainingScope(IASTDeclaration declaration) { - IASTNode parent = declaration.getParent(); - if( parent instanceof IASTTranslationUnit ){ - return ((IASTTranslationUnit)parent).getScope(); - } else if( parent instanceof IASTDeclarationStatement ){ - return getContainingScope( (IASTStatement) parent ); - } else if( parent instanceof IASTForStatement ){ - return ((IASTForStatement)parent).getScope(); - } else if( parent instanceof IASTCompositeTypeSpecifier ){ - return ((IASTCompositeTypeSpecifier)parent).getScope(); - } else if( parent instanceof ICPPASTNamespaceDefinition ) { - return ((ICPPASTNamespaceDefinition)parent).getScope(); - } - - return null; - } - + public static IScope getContainingScope( IASTStatement statement ){ IASTNode parent = statement.getParent(); IScope scope = null; @@ -588,59 +577,46 @@ public class CPPVisitor { return scope; } - public static IScope getContainingScope( IASTDeclSpecifier typeSpec ){ - IASTNode parent = typeSpec.getParent(); - if( parent instanceof IASTSimpleDeclaration ) - return getContainingScope( (IASTSimpleDeclaration) parent ); - else if( parent instanceof IASTTypeId ) - return getContainingScope( parent.getParent() ); - return getContainingScope( parent ); - } - - /** - * @param parameterDeclaration - * @return - */ - public static IScope getContainingScope(IASTParameterDeclaration parameterDeclaration) { - ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) parameterDeclaration.getParent(); - ASTNodeProperty prop = dtor.getPropertyInParent(); - if( prop == IASTSimpleDeclaration.DECLARATOR || prop == IASTFunctionDefinition.DECLARATOR ) - return dtor.getFunctionScope(); - - return getContainingScope( dtor ); - } - public static IASTNode getContainingBlockItem( IASTNode node ){ IASTNode parent = node.getParent(); if( parent == null ) return null; - - if( parent instanceof IASTDeclaration ){ - IASTNode p = parent.getParent(); - if( p instanceof IASTDeclarationStatement ) - return p; - return parent; - } else if( parent instanceof IASTExpression ){ - IASTNode p = parent.getParent(); - if( p instanceof IASTStatement ) - return p; - } else if ( parent instanceof IASTStatement || parent instanceof IASTTranslationUnit ) { - return parent; - } else if( parent instanceof IASTFunctionDeclarator ){ - return node; + while( parent != null ) { + if( parent instanceof IASTDeclaration ){ + IASTNode p = parent.getParent(); + if( p instanceof IASTDeclarationStatement ) + return p; + return parent; + } else if( parent instanceof IASTExpression ){ + IASTNode p = parent.getParent(); + if( p instanceof IASTStatement ) + return p; + } else if ( parent instanceof IASTStatement || parent instanceof IASTTranslationUnit ) { + return parent; + } else if( parent instanceof IASTFunctionDeclarator ){ + return node; + } + node = parent; + parent = node.getParent(); } - - return getContainingBlockItem( parent ); + return null; } static private IBinding resolveBinding( IASTNode node ){ - if( node instanceof IASTIdExpression ){ - return CPPSemantics.resolveBinding( ((IASTIdExpression)node).getName() ); - } else if( node instanceof ICPPASTFieldReference ){ - return CPPSemantics.resolveBinding( ((ICPPASTFieldReference)node).getFieldName() ); - } else if( node instanceof IASTFunctionCallExpression ){ - return resolveBinding( ((IASTFunctionCallExpression)node).getFunctionNameExpression() ); + while( node != null ) { + if( node instanceof IASTIdExpression ){ + return CPPSemantics.resolveBinding( ((IASTIdExpression)node).getName() ); + } else if( node instanceof ICPPASTFieldReference ){ + return CPPSemantics.resolveBinding( ((ICPPASTFieldReference)node).getFieldName() ); + } else if( node instanceof IASTFunctionCallExpression ){ + node = ((IASTFunctionCallExpression)node).getFunctionNameExpression(); + } else if( node instanceof IASTUnaryExpression ){ + node = ((IASTUnaryExpression)node).getOperand(); + } else if( node instanceof IASTBinaryExpression ){ + node = ((IASTBinaryExpression)node).getOperand2(); + } } + return null; } @@ -1487,7 +1463,9 @@ public class CPPVisitor { private static IType getPointerTypes( IType type, IASTDeclarator declarator ){ IASTPointerOperator [] ptrOps = declarator.getPointerOperators(); for( int i = ptrOps.length - 1; i >= 0; i-- ){ - if( ptrOps[i] instanceof IASTPointer ) + if( ptrOps[i] instanceof ICPPASTPointerToMember ) + type = new CPPPointerToMemberType( type, (ICPPASTPointerToMember) ptrOps[i] ); + else if( ptrOps[i] instanceof IASTPointer ) type = new CPPPointerType( type, (IASTPointer) ptrOps[i] ); else if( ptrOps[i] instanceof ICPPASTReferenceOperator ) type = new CPPReferenceType( type ); @@ -1652,7 +1630,17 @@ public class CPPVisitor { } catch ( DOMException e ) { return e.getProblem(); } - + } else if( binding instanceof IVariable ){ + try { + IType t = ((IVariable)binding).getType(); + if( t instanceof IPointerType && ((IPointerType)t).getType() instanceof IFunctionType ){ + IFunctionType ftype = (IFunctionType) ((IPointerType)t).getType(); + if( ftype != null ) + return ftype.getReturnType(); + } + } catch( DOMException e ){ + return e.getProblem(); + } } } else if( expression instanceof IASTUnaryExpression )