From ae97aa9b2a6894455ca3f50f82ba5e94c54bbe4d Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Fri, 4 Feb 2005 21:57:48 +0000 Subject: [PATCH] fix bug 84228 for C++ --- .../core/parser/tests/ast2/AST2CPPTests.java | 28 +++++++++ .../cdt/core/parser/tests/ast2/AST2Tests.java | 2 +- .../ast/cpp/ICPPASTFunctionDeclarator.java | 1 + .../parser/cpp/CPPASTFunctionDeclarator.java | 16 ++++- .../parser/cpp/CPPASTFunctionDefinition.java | 7 +-- .../core/dom/parser/cpp/CPPFunctionScope.java | 32 +++++++--- .../core/dom/parser/cpp/CPPSemantics.java | 63 ++++++++++++++----- .../core/dom/parser/cpp/CPPVisitor.java | 50 +++++---------- 8 files changed, 133 insertions(+), 66 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 86e65f4e085..5eb5171fc59 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 @@ -1054,5 +1054,33 @@ public class AST2CPPTests extends AST2BaseTest { s = (ICompositeType) col.getName(0).resolveBinding(); assertNotNull( s ); } + + public void testBug84228() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "void f( int m, int c[m][m] ); \n" ); //$NON-NLS-1$ + buffer.append( "void f( int m, int c[m][m] ){ \n" ); //$NON-NLS-1$ + buffer.append( " int x; \n" ); //$NON-NLS-1$ + buffer.append( " { int x = x; } \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); + + assertEquals(col.size(), 13); + + IParameter m = (IParameter) col.getName(3).resolveBinding(); + IVariable x3 = (IVariable) col.getName(12).resolveBinding(); + IVariable x2 = (IVariable) col.getName(11).resolveBinding(); + IVariable x1 = (IVariable) col.getName(10).resolveBinding(); + + assertSame( x2, x3 ); + assertNotSame( x1, x2 ); + + assertInstances( col, m, 6 ); + assertInstances( col, x1, 1 ); + assertInstances( col, x2, 2 ); + } + } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 80ddd78facb..39fe886193e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -2788,7 +2788,7 @@ public class AST2Tests extends AST2BaseTest { assertEquals(col.size(), 13); - IParameter m = (IParameter) col.getName(1).resolveBinding(); + IParameter m = (IParameter) col.getName(3).resolveBinding(); IVariable x3 = (IVariable) col.getName(12).resolveBinding(); IVariable x2 = (IVariable) col.getName(11).resolveBinding(); IVariable x1 = (IVariable) col.getName(10).resolveBinding(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java index 77919404d71..5ad94aefb2d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java @@ -41,4 +41,5 @@ public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarato public ICPPASTConstructorChainInitializer[] getConstructorChain(); public void addConstructorToChain( ICPPASTConstructorChainInitializer initializer ); + public ICPPFunctionScope getFunctionScope(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java index d8de0c13598..67b96f41810 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDeclarator.java @@ -10,10 +10,14 @@ **********************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTTypeId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; /** * @author jcamelon @@ -23,7 +27,7 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements private IASTParameterDeclaration [] parameters = null; private static final int DEFAULT_PARAMETERS_LIST_SIZE = 2; - + private ICPPFunctionScope scope = null; private int currentIndex = 0; private boolean varArgs; private boolean pureVirtual; @@ -232,6 +236,14 @@ public class CPPASTFunctionDeclarator extends CPPASTDeclarator implements constructorChain[ currentConstructorChainIndex++ ] = initializer; } - + public ICPPFunctionScope getFunctionScope(){ + if( scope != null ) + return scope; + + ASTNodeProperty prop = getPropertyInParent(); + if( prop == IASTSimpleDeclaration.DECLARATOR || prop == IASTFunctionDefinition.DECLARATOR ) + scope = new CPPFunctionScope( this ); + return scope; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDefinition.java index eb50b6b9874..177ca2b8d4d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDefinition.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTFunctionDefinition.java @@ -15,7 +15,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; /** * @author jcamelon @@ -26,7 +26,6 @@ public class CPPASTFunctionDefinition extends CPPASTNode implements private IASTDeclSpecifier declSpecifier; private IASTFunctionDeclarator declarator; private IASTStatement bodyStatement; - private ICPPFunctionScope scope; /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition#getDeclSpecifier() @@ -74,9 +73,7 @@ public class CPPASTFunctionDefinition extends CPPASTNode implements * @see org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition#getScope() */ public IScope getScope() { - if( scope == null ) - scope = new CPPFunctionScope( this ); - return scope; + return ((ICPPASTFunctionDeclarator)declarator).getFunctionScope(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java index 8cb6b8005c2..e9dec11fcc6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java @@ -16,14 +16,15 @@ 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.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; -import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.ILabel; import org.eclipse.cdt.core.dom.ast.IScope; +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.ICPPFunctionScope; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; /** @@ -36,7 +37,7 @@ public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope { /** * @param physicalNode */ - public CPPFunctionScope(IASTFunctionDefinition physicalNode) { + public CPPFunctionScope(IASTFunctionDeclarator physicalNode) { super(physicalNode); } @@ -71,12 +72,23 @@ public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope { } public IScope getParent() throws DOMException { - IASTFunctionDefinition fn = (IASTFunctionDefinition) getPhysicalNode(); - IFunction function = (IFunction) fn.getDeclarator().getName().resolveBinding(); - if( function instanceof ICPPMethod ){ - return function.getScope(); - } - return super.getParent(); + //we can't just resolve the function and get its parent scope, since there are cases where that + //could loop since resolving functions requires resolving their parameter types + IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) getPhysicalNode(); + IASTName name = fdtor.getName(); + if( name instanceof ICPPASTQualifiedName ){ + IASTName [] ns = ((ICPPASTQualifiedName)name).getNames(); + if( ns.length > 1){ + IBinding binding = ns[ ns.length - 2 ].resolveBinding(); + if( binding instanceof ICPPClassType ) + return ((ICPPClassType)binding).getCompositeScope(); + else if( binding instanceof ICPPNamespace ) + return ((ICPPNamespace)binding).getNamespaceScope(); + return binding.getScope(); + } + } + + return CPPVisitor.getContainingScope( fdtor ); } } 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 dd9867d1496..c4aa791f899 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 @@ -121,6 +121,16 @@ public class CPPSemantics { astName = null; this.name = n; } + public boolean includeBlockItem( IASTNode item ){ + if( astName == null ) return false; + if( astName.getParent() instanceof IASTIdExpression || + item instanceof IASTNamespaceDefinition || + (item instanceof IASTSimpleDeclaration && ((IASTSimpleDeclaration)item).getDeclSpecifier() instanceof IASTCompositeTypeSpecifier ) ) + { + return true; + } + return false; + } public boolean typesOnly(){ if( astName == null ) return false; IASTNode parent = astName.getParent(); @@ -649,8 +659,14 @@ public class CPPSemantics { List found = null; if( parent instanceof IASTCompoundStatement ){ - IASTCompoundStatement compound = (IASTCompoundStatement) parent; - nodes = compound.getStatements(); + if( parent.getParent() instanceof IASTFunctionDefinition ){ + ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition)parent.getParent()).getDeclarator(); + nodes = dtor.getParameters(); + } + if( nodes == null || nodes.length == 0 ){ + IASTCompoundStatement compound = (IASTCompoundStatement) parent; + nodes = compound.getStatements(); + } } else if ( parent instanceof IASTTranslationUnit ){ IASTTranslationUnit translation = (IASTTranslationUnit) parent; nodes = translation.getDeclarations(); @@ -664,6 +680,9 @@ public class CPPSemantics { nodes = ((ICPPASTNamespaceDefinition)namespaceDefs[0].getParent()).getDeclarations(); namespaceIdx = -1; + } else if( parent instanceof ICPPASTFunctionDeclarator ){ + ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) parent; + nodes = dtor.getParameters(); } if( scope instanceof ICPPClassScope ){ @@ -676,14 +695,8 @@ public class CPPSemantics { while( item != null ) { if( item == null || ( blockItem != null && ((ASTNode)item).getOffset() > ((ASTNode) blockItem).getOffset() )) break; - if( item == blockItem ){ - if( !(item instanceof IASTNamespaceDefinition) && - !(item instanceof IASTSimpleDeclaration && - ((IASTSimpleDeclaration)item).getDeclSpecifier() instanceof IASTCompositeTypeSpecifier) ) - { - break; - } - } + if( item == blockItem && !data.includeBlockItem( item ) ) + break; if( item instanceof ICPPASTUsingDirective && !data.ignoreUsingDirectives ) { if( usingDirectives != null ) @@ -696,18 +709,32 @@ public class CPPSemantics { found.add( possible ); } } + if( item == blockItem ) + break; if( idx > -1 && ++idx < nodes.length ){ item = nodes[idx]; } else { item = null; - while( namespaceIdx > -1 && namespaceDefs.length > ++namespaceIdx ){ - nodes = ((ICPPASTNamespaceDefinition)namespaceDefs[0].getParent()).getDeclarations(); - if( nodes.length > 0 ){ + if( namespaceIdx > -1 ) { + //check all definitions of this namespace + while( namespaceIdx > -1 && namespaceDefs.length > ++namespaceIdx ){ + nodes = ((ICPPASTNamespaceDefinition)namespaceDefs[0].getParent()).getDeclarations(); + if( nodes.length > 0 ){ + idx = 0; + item = nodes[0]; + break; + } + } + } else if( parent instanceof IASTCompoundStatement && nodes instanceof IASTParameterDeclaration [] ){ + //function body, we were looking at parameters, now check the body itself + IASTCompoundStatement compound = (IASTCompoundStatement) parent; + nodes = compound.getStatements(); + if( nodes.length > 0 ){ idx = 0; item = nodes[0]; break; - } + } } } } @@ -760,7 +787,13 @@ public class CPPSemantics { declaration = ((IASTDeclarationStatement)node).getDeclaration(); else if( node instanceof IASTForStatement ) declaration = ((IASTForStatement)node).getInitDeclaration(); - + else if( node instanceof IASTParameterDeclaration && !data.typesOnly() ){ + IASTParameterDeclaration parameterDeclaration = (IASTParameterDeclaration) node; + IASTName declName = parameterDeclaration.getDeclarator().getName(); + if( CharArrayUtils.equals( declName.toCharArray(), data.name ) ){ + return declName; + } + } if( declaration == null ) return null; 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 18d3da40766..2fcb9062983 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 @@ -16,6 +16,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp; import java.util.ArrayList; +import org.eclipse.cdt.core.dom.ast.ASTNodeProperty; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator; import org.eclipse.cdt.core.dom.ast.IASTArrayModifier; @@ -488,7 +489,7 @@ public class CPPVisitor { } else if( parent instanceof IASTCompoundStatement ){ return ((IASTCompoundStatement)parent).getScope(); } else if( parent instanceof ICPPASTConstructorChainInitializer ){ - IASTNode node = getContainingBlockItem( parent ); + IASTNode node = getContainingBlockItem( parent.getParent() ); if( node instanceof IASTFunctionDefinition ){ IASTCompoundStatement body = (IASTCompoundStatement) ((IASTFunctionDefinition)node).getBody(); return body.getScope(); @@ -555,44 +556,27 @@ public class CPPVisitor { } else if( parent instanceof IASTStatement ){ scope = getContainingScope( (IASTStatement)parent ); } else if( parent instanceof IASTFunctionDefinition ){ - IASTFunctionDeclarator fnDeclarator = ((IASTFunctionDefinition) parent ).getDeclarator(); + IASTFunctionDeclarator fnDeclarator = ((IASTFunctionDefinition) parent ).getDeclarator(); IFunction function = (IFunction) fnDeclarator.getName().resolveBinding(); + try { - scope = function.getFunctionScope(); - } catch ( DOMException e ) { - return e.getProblem(); - } + scope = function.getScope(); + } catch ( DOMException e ) { + } } if( statement instanceof IASTGotoStatement || statement instanceof IASTLabelStatement ){ - //labels have function scope - while( scope != null && !(scope instanceof ICPPFunctionScope) ){ - try { - scope = scope.getParent(); - } catch ( DOMException e ) { - return e.getProblem(); - } + while( !(parent instanceof IASTFunctionDefinition) ){ + parent = parent.getParent(); } + IASTFunctionDefinition fdef = (IASTFunctionDefinition) parent; + return ((ICPPASTFunctionDeclarator)fdef.getDeclarator()).getFunctionScope(); } return scope; } public static IScope getContainingScope( IASTDeclSpecifier typeSpec ){ -// if( typeSpec instanceof ICPPASTCompositeTypeSpecifier ){ -// ICPPASTCompositeTypeSpecifier compTypeSpec = (ICPPASTCompositeTypeSpecifier) typeSpec; -// IASTName name = compTypeSpec.getName(); -// if( name instanceof ICPPASTQualifiedName ){ -// IASTName [] names = ((ICPPASTQualifiedName)name).getNames(); -// if( names.length > 1 ){ -// IBinding binding = names[ names.length - 2 ].resolveBinding(); -// if( binding instanceof ICPPClassType ) -// return ((ICPPClassType)binding).getCompositeScope(); -// else if( binding instanceof ICPPNamespace ) -// return ((ICPPNamespace)binding).getNamespaceScope(); -// } -// } -// } IASTNode parent = typeSpec.getParent(); if( parent instanceof IASTSimpleDeclaration ) return getContainingScope( (IASTSimpleDeclaration) parent ); @@ -607,12 +591,10 @@ public class CPPVisitor { */ public static IScope getContainingScope(IASTParameterDeclaration parameterDeclaration) { ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) parameterDeclaration.getParent(); - IASTName name = dtor.getName(); - if( name instanceof ICPPASTQualifiedName ) { - IASTName[] ns = ((ICPPASTQualifiedName) name).getNames(); - if( ns.length > 0 ) - return getContainingScope( ns [ ns.length - 1 ] ); - } + ASTNodeProperty prop = dtor.getPropertyInParent(); + if( prop == IASTSimpleDeclaration.DECLARATOR || prop == IASTFunctionDefinition.DECLARATOR ) + return dtor.getFunctionScope(); + return getContainingScope( dtor ); } @@ -632,6 +614,8 @@ public class CPPVisitor { return p; } else if ( parent instanceof IASTStatement || parent instanceof IASTTranslationUnit ) { return parent; + } else if( parent instanceof IASTFunctionDeclarator ){ + return node; } return getContainingBlockItem( parent );