From 81150f40fe2b97d6c03ea4ca808122e69f273b0d Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Fri, 8 Apr 2005 19:14:18 +0000 Subject: [PATCH] fix 90253. also clean up CVisitor creating bindings off declarators --- .../cdt/core/parser/tests/ast2/AST2Tests.java | 53 +++++ .../core/dom/parser/c/CArrayType.java | 19 ++ .../core/dom/parser/c/CPointerType.java | 17 ++ .../core/dom/parser/c/CQualifierType.java | 17 ++ .../internal/core/dom/parser/c/CScope.java | 34 +-- .../internal/core/dom/parser/c/CVisitor.java | 208 ++++++++---------- 6 files changed, 206 insertions(+), 142 deletions(-) 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 341801dc27c..19ca09a9cdb 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 @@ -46,6 +46,7 @@ import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBasicType; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; @@ -3014,4 +3015,56 @@ public class AST2Tests extends AST2BaseTest { IFunction f = (IFunction) col.getName(0).resolveBinding(); assertFalse( f.isStatic() ); } + + public void testBug90253() throws Exception { + IASTTranslationUnit tu = parse( "void f(int par) { int v1; };", ParserLanguage.C ); //$NON-NLS-1$ + CNameCollector col = new CNameCollector(); + tu.accept( col ); + + IFunction f = (IFunction) col.getName(0).resolveBinding(); + IParameter p = (IParameter) col.getName(1).resolveBinding(); + IVariable v1 = (IVariable) col.getName(2).resolveBinding(); + + IScope scope = f.getFunctionScope(); + + IBinding [] bs = scope.find( "par" ); //$NON-NLS-1$ + assertEquals( bs.length, 1 ); + assertSame( bs[0], p ); + + bs = scope.find( "v1" ); //$NON-NLS-1$ + assertEquals( bs.length, 1 ); + assertSame( bs[0], v1 ); + } + + public void testFind() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append( "struct S {}; \n"); //$NON-NLS-1$ + buffer.append( "int S; \n"); //$NON-NLS-1$ + buffer.append( "void f( ) { \n"); //$NON-NLS-1$ + buffer.append( " int S; \n"); //$NON-NLS-1$ + buffer.append( " { \n"); //$NON-NLS-1$ + buffer.append( " S : ; \n"); //$NON-NLS-1$ + buffer.append( " } \n"); //$NON-NLS-1$ + buffer.append( "} \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.C ); + CNameCollector col = new CNameCollector(); + tu.accept( col ); + + ICompositeType S1 = (ICompositeType) col.getName(0).resolveBinding(); + IVariable S2 = (IVariable) col.getName(1).resolveBinding(); + IFunction f = (IFunction) col.getName(2).resolveBinding(); + IVariable S3 = (IVariable) col.getName(3).resolveBinding(); + ILabel S4 = (ILabel) col.getName(4).resolveBinding(); + + IScope scope = f.getFunctionScope(); + + IBinding [] bs = scope.find( "S" ); //$NON-NLS-1$ + + assertNotNull( S2 ); + assertEquals( bs.length, 3 ); + assertSame( bs[0], S3 ); + assertSame( bs[1], S1 ); + assertSame( bs[2], S4 ); + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java index 8bb84e75cf1..665fdc5a370 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CArrayType.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.c.ICASTArrayModifier; import org.eclipse.cdt.core.dom.ast.c.ICArrayType; @@ -27,6 +28,24 @@ public class CArrayType implements ICArrayType, ITypeContainer { this.type = type; } + public boolean equals(Object obj) { + if( obj instanceof ICArrayType ){ + ICArrayType at = (ICArrayType) obj; + try { + if( isConst() != at.isConst() ) return false; + if( isRestrict() != at.isRestrict() ) return false; + if( isStatic() != at.isStatic() ) return false; + if( isVolatile() != at.isVolatile() ) return false; + if( isVariableLength() != at.isVariableLength() ) return false; + + return at.getType().equals( type ); + } catch ( DOMException e ) { + return false; + } + } + return false; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IArrayType#getType() */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CPointerType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CPointerType.java index 5bcda02c7e5..48d364ef7b1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CPointerType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CPointerType.java @@ -10,6 +10,7 @@ **********************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.c.ICASTPointer; import org.eclipse.cdt.core.dom.ast.c.ICPointerType; @@ -29,6 +30,22 @@ public class CPointerType implements ICPointerType, ITypeContainer { this.nextType = next; } + public boolean equals( Object obj ){ + if( obj instanceof ICPointerType ){ + ICPointerType pt = (ICPointerType) obj; + try { + if( isConst() != pt.isConst() ) return false; + if( isRestrict() != pt.isRestrict() ) return false; + if( isVolatile() != pt.isVolatile() ) return false; + + return pt.getType().equals( nextType ); + } catch ( DOMException e ) { + return false; + } + } + return false; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.c.ICPointerType#isRestrict() */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java index 35010961485..9cdce3bb7a1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CQualifierType.java @@ -10,6 +10,7 @@ **********************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; @@ -37,6 +38,22 @@ public class CQualifierType implements ICQualifierType, ITypeContainer { this.declSpec = declSpec; } + public boolean equals( Object obj ){ + if( obj instanceof ICQualifierType ){ + ICQualifierType qt = (ICQualifierType) obj; + try { + if( isConst() != qt.isConst() ) return false; + if( isRestrict() != qt.isRestrict() ) return false; + if( isVolatile() != qt.isVolatile() ) return false; + + return qt.getType().equals( getType() ); + } catch ( DOMException e ) { + return false; + } + } + return false; + } + /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IQualifierType#isConst() */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java index 15146cd851f..9dda316b408 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java @@ -78,7 +78,7 @@ public class CScope implements ICScope { prop == IASTDeclarator.DECLARATOR_NAME ) { if( CharArrayUtils.equals( n.toCharArray(), name ) ) - result = (IASTName[]) ArrayUtil.append( IASTName.class, result, name ); + result = (IASTName[]) ArrayUtil.append( IASTName.class, result, n ); } return PROCESS_CONTINUE; @@ -95,35 +95,10 @@ public class CScope implements ICScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String) */ - public IBinding[] find( String name ) { - IASTNode node = getPhysicalNode(); - CollectNamesAction action = new CollectNamesAction( name.toCharArray() ); - node.accept( action ); - - IASTName [] names = action.getNames(); - IBinding [] result = null; - for( int i = 0; i < names.length; i++ ){ - IBinding b = names[i].resolveBinding(); - if( b == null ) continue; - try { - if( b.getScope() == this ) - result = (IBinding[]) ArrayUtil.append( IBinding.class, result, b ); - } catch ( DOMException e ) { - } - } - - return (IBinding[]) ArrayUtil.trim( IBinding.class, result ); + public IBinding[] find( String name ) throws DOMException { + return CVisitor.findBindings( this, name ); } -// public void addBinding( IBinding binding ) { -// int type = ( binding instanceof ICompositeType || binding instanceof IEnumeration ) ? -// NAMESPACE_TYPE_TAG : NAMESPACE_TYPE_OTHER; -// -// if( bindings[type] == CharArrayObjectMap.EMPTY_MAP ) -// bindings[type] = new CharArrayObjectMap(1); -// bindings[type].put( binding.getNameCharArray(), binding ); -// } - public IBinding getBinding( int namespaceType, char [] name ){ IASTName n = (IASTName) bindings[namespaceType].get( name ); return ( n != null ) ? n.resolveBinding() : null; @@ -168,7 +143,8 @@ public class CScope implements ICScope { ASTNodeProperty prop = name.getPropertyInParent(); if( prop == IASTCompositeTypeSpecifier.TYPE_NAME || prop == IASTElaboratedTypeSpecifier.TYPE_NAME || - prop == IASTEnumerationSpecifier.ENUMERATION_NAME ) + prop == IASTEnumerationSpecifier.ENUMERATION_NAME || + prop == CVisitor.STRING_LOOKUP_TAGS_PROPERTY ) { return NAMESPACE_TYPE_TAG; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index b08a538cd5f..a4e45b38bd2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -56,6 +56,7 @@ import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.ILabel; +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.IScope; @@ -423,6 +424,9 @@ public class CVisitor { } } + protected static final ASTNodeProperty STRING_LOOKUP_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$ + protected static final ASTNodeProperty STRING_LOOKUP_TAGS_PROPERTY = new ASTNodeProperty("CVisitor.STRING_LOOKUP_TAGS_PROPERTY - STRING_LOOKUP"); //$NON-NLS-1$ + //lookup bits private static final int COMPLETE = 0; private static final int CURRENT_SCOPE = 1; @@ -648,18 +652,8 @@ public class CVisitor { */ private static IBinding createBinding(IASTDeclarator declarator, IASTName name) { IBinding binding = null; - IASTNode parent = declarator.getParent(); - if( declarator instanceof IASTStandardFunctionDeclarator ){ - binding = resolveBinding( parent, CURRENT_SCOPE ); - if( binding != null ) { - if( binding instanceof IFunction ) - ((CFunction)binding).addDeclarator( (IASTStandardFunctionDeclarator) declarator ); - else - binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray() ); - } else { - binding = createBinding(declarator); - } - } else if( declarator instanceof ICASTKnRFunctionDeclarator ){ + if( declarator instanceof ICASTKnRFunctionDeclarator ){ + IASTNode parent = declarator.getParent(); if ( CharArrayUtils.equals(declarator.getName().toCharArray(), name.toCharArray()) ){ binding = resolveBinding( parent, CURRENT_SCOPE ); if( binding != null ) { @@ -685,40 +679,21 @@ public class CVisitor { } } } - } else if( parent instanceof IASTSimpleDeclaration ){ - binding = createBinding( (IASTSimpleDeclaration) parent, name ); - } else if( parent instanceof IASTParameterDeclaration ){ - IASTParameterDeclaration param = (IASTParameterDeclaration) parent; - IASTFunctionDeclarator fDtor = (IASTFunctionDeclarator) param.getParent(); - IBinding b = fDtor.getName().resolveBinding(); - if( b instanceof IFunction ){ - binding = ((CFunction)b).resolveParameter( name ); - parent = fDtor.getParent(); - if( parent instanceof IASTFunctionDefinition ){ - ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope(); - if ( scope != null && binding != null ) - try { - scope.addName(name); - } catch ( DOMException e ) { - } - } - } - } else if ( parent instanceof IASTDeclarator ) { - binding = createBinding(declarator); + } else { + binding = createBinding( declarator ); } - return binding; } private static IBinding createBinding( IASTDeclarator declarator ){ IASTNode parent = declarator.getParent(); - if( declarator.getNestedDeclarator() != null ) - return createBinding( declarator.getNestedDeclarator() ); - while( parent instanceof IASTDeclarator ){ parent = parent.getParent(); } + + while( declarator.getNestedDeclarator() != null ) + declarator = declarator.getNestedDeclarator(); ICScope scope = (ICScope) getContainingScope( parent ); @@ -730,65 +705,66 @@ public class CVisitor { scope = null; } + IASTName name = declarator.getName(); + IBinding binding = null; try { - binding = ( scope != null ) ? scope.getBinding( declarator.getName(), false ) : null; + binding = ( scope != null ) ? scope.getBinding( name, false ) : null; } catch ( DOMException e1 ) { binding = null; } - if( declarator instanceof IASTFunctionDeclarator ){ - if( binding != null && binding instanceof IFunction ){ - try{ + if( parent instanceof IASTParameterDeclaration || parent.getPropertyInParent() == ICASTKnRFunctionDeclarator.FUNCTION_PARAMETER ){ + IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) parent.getParent(); + IBinding temp = fdtor.getName().resolveBinding(); + if( temp != null && temp instanceof IFunction ){ + binding = ((CFunction) temp).resolveParameter( name ); + } + } else if( declarator instanceof IASTFunctionDeclarator ){ + if( binding != null ) { + if( binding instanceof IFunction ){ IFunction function = (IFunction) binding; - IFunctionType ftype = function.getType(); - IType type = createType( declarator ); - if( ftype.equals( type ) ){ - if( parent instanceof IASTSimpleDeclaration ) - ((CFunction)function).addDeclarator( (IASTFunctionDeclarator) declarator ); - - return function; - } - } catch( DOMException e ){ + ((CFunction)function).addDeclarator( (IASTFunctionDeclarator) declarator ); + return function; } - } - - if( parent instanceof IASTSimpleDeclaration && ((IASTSimpleDeclaration) parent).getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) - binding = new CTypeDef( declarator.getName() ); + binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray() ); + } else if( parent instanceof IASTSimpleDeclaration && ((IASTSimpleDeclaration) parent).getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) + binding = new CTypeDef( name ); else binding = new CFunction( (IASTFunctionDeclarator) declarator ); } else if( parent instanceof IASTSimpleDeclaration ){ IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent; if( simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ - binding = new CTypeDef( declarator.getName() ); + binding = new CTypeDef( name ); } else { IType t1 = null, t2 = null; - if( binding != null && binding instanceof IVariable ){ - t1 = createType( declarator ); - try { - t2 = ((IVariable)binding).getType(); - } catch ( DOMException e1 ) { - } - } - if( t1 != null && t2 != null && t1.equals( t2 ) ){ - ((CVariable)binding).addDeclaration( declarator.getName() ); + if( binding != null ) { + if( binding instanceof IParameter ){ + return new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray() ); + } else if( binding instanceof IVariable ){ + t1 = createType( declarator ); + try { + t2 = ((IVariable)binding).getType(); + } catch ( DOMException e1 ) { + } + if( t1 != null && t2 != null && t1.equals( t2 ) ){ + if( binding instanceof CVariable ) + ((CVariable)binding).addDeclaration( name ); + } else { + return new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray() ); + } + } } else if( simpleDecl.getParent() instanceof ICASTCompositeTypeSpecifier ){ - binding = new CField( declarator.getName() ); + binding = new CField( name ); } else { - binding = new CVariable( declarator.getName() ); + binding = new CVariable( name ); } } - } else if( parent instanceof IASTParameterDeclaration ){ - IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) parent.getParent(); - IBinding temp = fdtor.getName().resolveBinding(); - if( temp != null && temp instanceof IFunction ){ - binding = ((CFunction) temp).resolveParameter( declarator.getName() ); - } } if( scope != null && binding != null ) try { - scope.addName( declarator.getName() ); + scope.addName( name ); } catch ( DOMException e ) { } return binding; @@ -823,47 +799,6 @@ public class CVisitor { return binding; } - - /** - * @param parent - * @return - */ - private static IBinding createBinding(IASTSimpleDeclaration simpleDeclaration, IASTName name) { - IBinding binding = null; - if( simpleDeclaration.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ){ - binding = new CTypeDef( name ); - try { - ((ICScope) binding.getScope()).addName( name ); - } catch ( DOMException e ) { - } - } else if( simpleDeclaration.getParent() instanceof ICASTCompositeTypeSpecifier ){ - binding = new CField( name ); - try { - ((ICScope) binding.getScope()).addName( name ); - } catch ( DOMException e ) { - } - } else { - CScope scope = (CScope) CVisitor.getContainingScope( simpleDeclaration ); - binding = scope.getBinding( name, false ); - if( binding == null ){ - // if the simpleDeclaration is part of a KRC function declarator, then the binding is to a KRC parameter - if ( simpleDeclaration.getParent() instanceof IASTFunctionDeclarator ) { - IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) simpleDeclaration.getParent(); - IBinding fn = fdtor.getName().resolveBinding(); - if( fn instanceof CFunction ){ - binding = ((CFunction)fn).resolveParameter( name ); - } - } else { - binding = new CVariable( name ); - } - - scope.addName( name ); - } - } - - return binding; - } - protected static IBinding resolveBinding( IASTNode node ){ return resolveBinding( node, COMPLETE ); } @@ -1765,4 +1700,51 @@ public class CVisitor { } return (IBinding[]) ArrayUtil.trim( IBinding.class, result ); } + + public static IBinding[] findBindings( IScope scope, String name ) throws DOMException{ + IASTNode node = scope.getPhysicalNode(); + if( node instanceof IASTFunctionDefinition ) + node = ((IASTFunctionDefinition)node).getBody(); + + CASTName astName = new CASTName( name.toCharArray() ); + astName.setParent( node ); + + //normal names + astName.setPropertyInParent( STRING_LOOKUP_PROPERTY ); + IBinding b1 = (IBinding) findBinding( astName, astName, COMPLETE ); + + //structure names + astName.setPropertyInParent( STRING_LOOKUP_TAGS_PROPERTY ); + IBinding b2 = (IBinding) findBinding( astName, astName, COMPLETE | TAGS ); + + //label names + ILabel b3 = null; + do{ + char [] n = name.toCharArray(); + if( scope instanceof ICFunctionScope ){ + ILabel [] labels = ((CFunctionScope)scope).getLabels(); + for( int i = 0; i < labels.length; i++ ){ + ILabel label = labels[i]; + if( CharArrayUtils.equals( label.getNameCharArray(), n) ){ + b3 = label; + break; + } + } + break; + } + scope = scope.getParent(); + } while( scope != null ); + + int c = (( b1 != null ) ? 1 : 0) + (( b2 != null ) ? 1 : 0) + (( b3 != null ) ? 1 : 0); + IBinding [] result = new IBinding [c]; + c = 0; + if( b1 != null ) + result[c++] = b1; + if( b2 != null ) + result[c++] = b2; + if( b3 != null ) + result[c] = b3; + + return result; + } }