From c20d990dc3cd77e03f86df9ed5c803dcdbb7b4ff Mon Sep 17 00:00:00 2001
From: Andrew Niefer <aniefer@ca.ibm.com>
Date: Thu, 13 Jan 2005 20:29:34 +0000
Subject: [PATCH] patch from Devin Steffler: removing IBindings from IScopes

---
 .../cdt/core/parser/tests/ast2/AST2Tests.java | 24 +++++++++++-
 .../eclipse/cdt/core/dom/ast/c/ICScope.java   |  1 +
 .../internal/core/dom/parser/c/CASTName.java  |  4 ++
 .../dom/parser/c/CCompositeTypeScope.java     |  9 +++++
 .../core/dom/parser/c/CFunctionScope.java     |  9 ++++-
 .../internal/core/dom/parser/c/CScope.java    | 12 ++++++
 .../internal/core/dom/parser/c/CVisitor.java  | 37 ++++++++++++++++---
 7 files changed, 89 insertions(+), 7 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 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 ){