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 872e7afb4ec..658295dd40d 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 @@ -68,6 +68,7 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator; import org.eclipse.cdt.core.dom.ast.c.ICASTPointer; import org.eclipse.cdt.core.dom.ast.c.ICArrayType; import org.eclipse.cdt.core.dom.ast.c.ICFunctionScope; +import org.eclipse.cdt.core.dom.ast.c.ICScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember; import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.internal.core.dom.parser.c.CFunction; @@ -153,7 +154,7 @@ public class AST2Tests extends AST2BaseTest { IFunction func_f = (IFunction) name_f.resolveBinding(); assertEquals(globalScope, func_f.getScope()); IParameter var_y = (IParameter) name_y.resolveBinding(); - assertEquals(func_f.getFunctionScope(), var_y.getScope()); + assertEquals(((IASTCompoundStatement)funcdef_f.getBody()).getScope(), var_y.getScope()); IVariable var_z = (IVariable) name_z.resolveBinding(); assertEquals(((ICFunctionScope)func_f.getFunctionScope()).getBodyScope(), var_z.getScope()); @@ -162,6 +163,15 @@ public class AST2Tests extends AST2BaseTest { assertEquals(var_x, name_ref_x.resolveBinding()); assertEquals(var_y, name_ref_y.resolveBinding()); + assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("f").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)body_f.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("z").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)body_f.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("y").toCharArray()) ); //$NON-NLS-1$ + CVisitor.clearBindings(tu); + assertNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("f").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)body_f.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("z").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)body_f.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("y").toCharArray()) ); //$NON-NLS-1$ } public void testSimpleStruct() throws ParserException { @@ -500,7 +510,19 @@ public class AST2Tests extends AST2BaseTest { assertNotNull( x2 ); assertSame( x1, x3 ); assertNotSame( x2, x3 ); + + IASTDeclarator decl_i = declaration.getDeclarators()[0]; + decl_i.getName().resolveBinding(); // add i's binding to the scope + assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_TAG, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("f").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)compound.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNotNull( ((ICScope)compound.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("i").toCharArray()) ); //$NON-NLS-1$ + CVisitor.clearBindings(tu); + assertNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_TAG, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("f").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)compound.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("x").toCharArray()) ); //$NON-NLS-1$ + assertNull( ((ICScope)compound.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("i").toCharArray()) ); //$NON-NLS-1$ } public void testFunctionParameters() throws Exception { StringBuffer buffer = new StringBuffer(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICScope.java index b89d3b1f219..05db6d79f4c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/c/ICScope.java @@ -25,5 +25,6 @@ public interface ICScope extends IScope { public static final int NAMESPACE_TYPE_OTHER = 1; void addBinding( IBinding binding ); + void removeBinding( IBinding binding ); public IBinding getBinding( int namespaceType, char [] name ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java index 1973a6e66a8..b5c2897cd51 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTName.java @@ -45,6 +45,10 @@ public class CASTName extends CASTNode implements IASTName { return binding; } + protected boolean hasBinding(){ + return ( binding != null ); + } + protected void setBinding( IBinding binding ){ this.binding = binding; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CCompositeTypeScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CCompositeTypeScope.java index 76ee525243b..d9ce488acdb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CCompositeTypeScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CCompositeTypeScope.java @@ -72,4 +72,13 @@ public class CCompositeTypeScope implements ICCompositeTypeScope { // TODO Auto-generated method stub return null; } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICScope#removeBinding(org.eclipse.cdt.core.dom.ast.IBinding) + */ + public void removeBinding(IBinding binding) { + if( bindings != CharArrayObjectMap.EMPTY_MAP ) { + bindings.remove( binding.getNameCharArray(), 0, binding.getNameCharArray().length); + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java index ee2d99d1ebe..834d5eba46a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CFunctionScope.java @@ -114,5 +114,12 @@ public class CFunctionScope implements ICFunctionScope { } } - + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICScope#removeBinding(org.eclipse.cdt.core.dom.ast.IBinding) + */ + public void removeBinding(IBinding binding) { + if( bindings != CharArrayObjectMap.EMPTY_MAP ) { + bindings.remove( binding.getNameCharArray(), 0, binding.getNameCharArray().length); + } + } } 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 827585f579f..387c79e722a 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 @@ -63,4 +63,16 @@ public class CScope implements ICScope { public IBinding getBinding( int namespaceType, char [] name ){ return (IBinding) bindings[namespaceType].get( name ); } + + /* (non-Javadoc) + * @see org.eclipse.cdt.core.dom.ast.c.ICScope#removeBinding(org.eclipse.cdt.core.dom.ast.IBinding) + */ + public void removeBinding(IBinding binding) { + int type = ( binding instanceof ICompositeType || binding instanceof IEnumeration ) ? + NAMESPACE_TYPE_TAG : NAMESPACE_TYPE_OTHER; + + if( bindings[type] != CharArrayObjectMap.EMPTY_MAP ) { + bindings[type].remove( binding.getNameCharArray(), 0, binding.getNameCharArray().length); + } + } } 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 3a92d124921..ed64d139d4d 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 @@ -212,6 +212,20 @@ public class CVisitor { return true; } } + + public static class ClearBindingFromScopeAction extends CBaseVisitorAction { + { + processNames = true; + } + public boolean processName(IASTName name) { + if ( ((CASTName)name).hasBinding() ) { + ICScope scope = (ICScope)name.resolveBinding().getScope(); + if ( scope != null ) + scope.removeBinding(name.resolveBinding()); + } + return true; + } + } //lookup bits private static final int COMPLETE = 0; @@ -348,6 +362,18 @@ public class CVisitor { binding = createBinding( (IASTSimpleDeclaration) parent, name ); } else if( parent instanceof IASTParameterDeclaration ){ binding = createBinding( (IASTParameterDeclaration ) parent ); + + // C99 6.2.1-4: within the list of parameter declarations in a function definition, the + // identifier has block scope, which terminates at the end of the associated block. + parent = parent.getParent(); + if ( parent instanceof IASTFunctionDeclarator ) { + parent = parent.getParent(); + if ( parent instanceof IASTFunctionDefinition ) { + ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope(); + if ( scope != null && binding != null ) + scope.addBinding(binding); + } + } } else if ( parent instanceof IASTFunctionDeclarator ) { binding = createBinding(declarator); } @@ -565,10 +591,10 @@ public class CVisitor { public static IScope getContainingScope(IASTParameterDeclaration parameterDeclaration) { IASTNode parent = parameterDeclaration.getParent(); if( parent instanceof IASTFunctionDeclarator ){ - IASTFunctionDeclarator functionDeclarator = (IASTFunctionDeclarator) parent; - IASTName fnName = functionDeclarator.getName(); - IFunction function = (IFunction) fnName.resolveBinding(); - return function.getFunctionScope(); + parent = ((IASTDeclarator)parent).getParent(); + if ( parent instanceof IASTFunctionDefinition ) { + return ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope(); + } } return null; @@ -806,7 +832,8 @@ public class CVisitor { } public static void clearBindings( IASTTranslationUnit tu ){ - visitTranslationUnit( tu, new ClearBindingAction() ); + visitTranslationUnit( tu, new ClearBindingFromScopeAction() ); + visitTranslationUnit( tu, new ClearBindingAction() ); } public static void visitTranslationUnit( IASTTranslationUnit tu, CBaseVisitorAction action ){