Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Implementation of Namespaces & using directives in ne w parser's symbol table

patch_03.05.03(cdt.core).txt contains the new parser's ParserSymbolTable
implementation of lookup of names in namespaces nominated by using
directives.

patch_03.05.03(cdt.ui.tests).txt contains the corresponding junit tests.

Andrew Niefer
Software Engineer
Rational Software - IBM Software Group
Ottawa (Kanata), Ontario, Canada

Index: parser/org/eclipse/cdt/internal/core/parser/Declaration.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java,v
retrieving revision 1.2
diff -u -r1.2 Declaration.java
--- parser/org/eclipse/cdt/internal/core/parser/Declaration.java	4 Mar 2003 18:25:40 -0000	1.2
+++ parser/org/eclipse/cdt/internal/core/parser/Declaration.java	5 Mar 2003 22:55:30 -0000
@@ -1,13 +1,19 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
 package org.eclipse.cdt.internal.core.parser;
 
 import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
-import java.util.Set;
 
 /**
  * @author aniefer
@@ -17,12 +23,13 @@
  * To enable and disable the creation of type comments go to
  * Window>Preferences>Java>Code Generation.
  */
+
 public class Declaration {
 
 	/**
 	 * Constructor for Declaration.
 	 */
-	public Declaration() {
+	public Declaration(){
 		super();
 	}
 
@@ -35,36 +42,139 @@
 		_object = obj;
 	}
 
-	//Type information, only what we need for now...
-	public static final int typeMask   = 0x0001f;
-	public static final int isStatic   = 0x00020;
-
-	// Types
-	public static final int t_type        = 0; // Type Specifier
-	public static final int t_class       = 1;
-	public static final int t_struct      = 2;
-	public static final int t_union       = 3;
-	public static final int t_enum        = 4;
+	public static final int typeMask   = 0x001f;
+	public static final int isAuto     = 0x0020;
+	public static final int isRegister = 0x0040;
+	public static final int isStatic   = 0x0080;
+	public static final int isExtern   = 0x0100;
+	public static final int isMutable  = 0x0200;
+	public static final int isInline   = 0x0400;
+	public static final int isVirtual  = 0x0800;
+	public static final int isExplicit = 0x1000;
+	public static final int isTypedef  = 0x2000;
+	public static final int isFriend   = 0x4000;
+	public static final int isConst    = 0x8000;
+	public static final int isVolatile = 0x10000;
+	public static final int isUnsigned = 0x20000;
+	public static final int isShort    = 0x40000;
+	public static final int isLong     = 0x80000;
+	
+	public void setAuto(boolean b) { setBit(b, isAuto); }
+	public boolean isAuto() { return checkBit(isAuto); }
+	
+	public void setRegister(boolean b) { setBit(b, isRegister); }
+	public boolean isRegister() { return checkBit(isRegister); } 
+	
+	public void setStatic(boolean b) { setBit(b, isStatic); }
+	public boolean isStatic() { return checkBit(isStatic); }
+	
+	public void setExtern(boolean b) { setBit(b, isExtern); }
+	public boolean isExtern() { return checkBit(isExtern); }
+	
+	public void setMutable(boolean b) { setBit(b, isMutable); }
+	public boolean isMutable() { return checkBit(isMutable); }
+	
+	public void setInline(boolean b) { setBit(b, isInline); }
+	public boolean isInline() { return checkBit(isInline); }
+	
+	public void setVirtual(boolean b) { setBit(b, isVirtual); }
+	public boolean isVirtual() { return checkBit(isVirtual); }
+	
+	public void setExplicit(boolean b) { setBit(b, isExplicit); }
+	public boolean isExplicit() { return checkBit(isExplicit); }
+	
+	public void setTypedef(boolean b) { setBit(b, isTypedef); }
+	public boolean isTypedef() { return checkBit(isTypedef); }
+	
+	public void setFriend(boolean b) { setBit(b, isFriend); }
+	public boolean isFriend() { return checkBit(isFriend); }
+	
+	public void setConst(boolean b) { setBit(b, isConst); }
+	public boolean isConst() { return checkBit(isConst); }
+	
+	public void setVolatile(boolean b) { setBit(b, isVolatile); }
+	public boolean isVolatile() { return checkBit(isVolatile); }
 
-	public void setStatic( boolean b ) { setBit( b, isStatic ); }
-	public boolean isStatic() { return checkBit( isStatic ); }
+	public void setUnsigned(boolean b) { setBit(b, isUnsigned); }
+	public boolean isUnsigned() {	return checkBit(isUnsigned); }
+	
+	public void setShort(boolean b) { setBit(b, isShort); }
+	public boolean isShort() { return checkBit(isShort); }
 
-	public void setType(int t) throws ParserSymbolTableException {
-		if( t > typeMask )
+	public void setLong(boolean b) { setBit(b, isLong); }
+	public boolean isLong() {	return checkBit(isLong); }
+	
+	// Types
+	// Note that these should be considered ordered and if you change
+	// the order, you should consider the ParserSymbolTable uses
+	public static final int t_type        =  0; // Type Specifier
+	public static final int t_namespace   =  1;
+	public static final int t_class       =  2;
+	public static final int t_struct      =  3;
+	public static final int t_union       =  4;
+	public static final int t_enum        =  5;
+	public static final int t_function    =  6;
+	public static final int t_char        =  7;
+	public static final int t_wchar_t     =  8;
+	public static final int t_bool        =  9;
+	public static final int t_int         = 10;
+	public static final int t_float       = 11;
+	public static final int t_double      = 12;
+	public static final int t_void        = 13;
+	public static final int t_enumerator  = 14;
+	
+
+	public void setType(int t) throws ParserSymbolTableException{ 
+		//sanity check, t must fit in its allocated 5 bits in _typeInfo
+		if( t > typeMask ){
 			throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
+		}
+		
 		_typeInfo = _typeInfo & ~typeMask | t; 
 	}
+	
 	public int getType(){ 
 		return _typeInfo & typeMask; 
 	}
-	public boolean isType( int t ){
-		return ( t == -1 || getType() == t );	
+	
+	public boolean isType( int type ){
+		return isType( type, 0 ); 
+	}
+	
+	/**
+	 * 
+	 * @param type
+	 * @param upperType
+	 * @return boolean
+	 * 
+	 * type checking, check that this declaration's type is between type and
+	 * upperType (inclusive).  upperType of 0 means no range and our type must
+	 * be type.
+	 */
+	public boolean isType( int type, int upperType ){
+		//type of -1 means we don't care
+		if( type == -1 )
+			return true;
+		
+		//upperType of 0 means no range
+		if( upperType == 0 ){
+			return ( getType() == type );
+		} else {
+			return ( getType() >= type && getType() <= upperType );
+		}
 	}
 		
-	public Declaration getTypeDeclaration() {	return _typeDeclaration; }
+	public Declaration getTypeDeclaration(){	
+		return _typeDeclaration; 
+	}
+	
 	public void setTypeDeclaration( Declaration type ){
-		try { setType( t_type ); }
-		catch (ParserSymbolTableException e) { /*will never happen*/ }
+		//setting our type to a declaration implies we are type t_type
+		try { 
+			setType( t_type ); 
+		} catch (ParserSymbolTableException e) { 
+			/*will never happen*/ 
+		}
 		
 		_typeDeclaration = type; 
 	}
@@ -76,137 +186,64 @@
 	public void setObject( Object obj ) { _object = obj; }
 	
 	public Declaration	getContainingScope() { return _containingScope; }
-	protected void setContainingScope( Declaration scope ) { _containingScope = scope; }
+	protected void setContainingScope( Declaration scope ){ 
+		_containingScope = scope;
+		_depth = scope._depth + 1; 
+	}
 	
 	public void addParent( Declaration parent ){
 		addParent( parent, false );
 	}
 	public void addParent( Declaration parent, boolean virtual ){
+		if( _parentScopes == null ){
+			_parentScopes = new LinkedList();
+		}
+			
 		_parentScopes.add( new ParentWrapper( parent, virtual ) );
 	}
-
-	protected void addDeclaration( Declaration obj ){
-		obj.setContainingScope( this );
-		_containedDeclarations.put( obj.getName(), obj );
-	}
 	
 	public Map getContainedDeclarations(){
 		return _containedDeclarations;
 	}
 	
-	/**
-	 * Lookup the given name in this context.
-	 * @param type: for elaborated lookups, only return declarations of this
-	 * 				 type
-	 * @param name: Name of the object to lookup
-	 * @return Declaration 
-	 * @throws ParserSymbolTableException
-	 * @see ParserSymbolTable#Lookup
-	 */
-	protected Declaration Lookup( int type, String name ) throws ParserSymbolTableException{
-		
-		if( type != -1 && type < t_class && type > t_union )
-			throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
-			
-		Declaration decl = null;
-		
-		//if this name define in this scope?
-		decl = (Declaration) _containedDeclarations.get( name );
+	public Map createContained(){
+		if( _containedDeclarations == null )
+			_containedDeclarations = new HashMap();
 		
-		//if yes, it hides any others, we are done.
-		if( decl != null && decl.isType( type ) ){
-			return decl; 
-		}
-
-		//if no, we next check any parents we have	
-		decl = LookupInParents( type, name, new HashSet() );	
-					
-		//if still not found, check our containing scope.			
-		if( decl == null && _containingScope != null ) 
-			decl = _containingScope.Lookup( type, name );
-
-		return decl;
+		return _containedDeclarations;
 	}
 
-	private Declaration LookupInParents( int type, String name, Set virtualsVisited ) throws ParserSymbolTableException{
-		
-		Declaration decl = null, temp = null;
-				
-		Iterator iterator = _parentScopes.iterator();
-		
-		ParentWrapper wrapper = null;
-		try{
-			wrapper = (ParentWrapper) iterator.next();
-		}
-		catch ( NoSuchElementException e ){
-			wrapper = null;
-		}
-		
-		while( wrapper != null )
-		{
-			if( !wrapper.isVirtual || !virtualsVisited.contains( wrapper.parent ) ){
-				if( wrapper.isVirtual )
-					virtualsVisited.add( wrapper.parent );
-					
-				//is this name define in this scope?
-				temp = (Declaration) wrapper.parent._containedDeclarations.get( name );
-				if( temp == null || !temp.isType( type ) )
-					temp = wrapper.parent.LookupInParents( type, name, virtualsVisited );
-			}	
-				
-			if( temp != null && temp.isType( type ) ){
-				if( decl == null  )
-					decl = temp;
-				else if ( temp != null )
-				{
-					//it is not ambiguous if temp & decl are the same thing and it is static
-					//or an enum
-					if( decl == temp && ( temp.isStatic() || temp.getType() == t_enum) )
-						temp = null;
-					else
-						throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) );
-		
-				}
-			}
-			else
-				temp = null;
-			
-			try{
-				wrapper = (ParentWrapper) iterator.next();
-			}
-			catch (NoSuchElementException e){
-				wrapper = null;	
-			}		
-		}
-		
-		return decl;	
+	public LinkedList getParentScopes(){
+		return _parentScopes;
 	}
 	
-
 	// Convenience methods
-	private void setBit(boolean b, int mask) {
-		if (b)	_typeInfo = _typeInfo | mask;
-		else	_typeInfo = _typeInfo & ~mask;
+	private void setBit(boolean b, int mask){
+		if( b ){
+			_typeInfo = _typeInfo | mask; 
+		} else {
+			_typeInfo = _typeInfo & ~mask; 
+		} 
 	}
 	
-	private boolean checkBit(int mask) {
+	private boolean checkBit(int mask){
 		return (_typeInfo & mask) != 0;
 	}	
 	
+	private 	int   		_typeInfo;				//our type info
+	private 	String 		_name;					//our name
+	private	Object 		_object;				//the object associated with us
+	private 	Declaration	_typeDeclaration;		//our type if _typeInfo says t_type
+	
+	protected	Declaration	_containingScope;		//the scope that contains us
+	protected	LinkedList 	_parentScopes;			//inherited scopes (is base classes)
+	protected	LinkedList 	_usingDirectives;		//collection of nominated namespaces
+	protected	Map    		_containedDeclarations;	//declarations contained by us.
 	
-	//Other scopes to check if the name is not in currRegion
-	//we might want another Vector to deal with namespaces & using...
-	private Declaration _containingScope  = null;
-	private Declaration _type             = null;
-	private Declaration _typeDeclaration  = null;
-	private int   _typeInfo               = 0;
-	private Object _object                = null;
-	private List   _parentScopes          = new LinkedList();
-	private Map    _containedDeclarations = new HashMap();
-	private String _name;
-	
+	protected	int 		_depth;					//how far down the scope stack we are
 		
-	private class ParentWrapper{
+	protected class ParentWrapper
+	{
 		public ParentWrapper( Declaration p, boolean v ){
 			parent    = p;
 			isVirtual = v;
@@ -215,6 +252,5 @@
 		public boolean isVirtual = false;
 		public Declaration parent = null;
 	}
-
-
+	
 }
Index: parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java,v
retrieving revision 1.2
diff -u -r1.2 ParserSymbolTable.java
--- parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	4 Mar 2003 18:25:40 -0000	1.2
+++ parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	5 Mar 2003 22:55:31 -0000
@@ -1,6 +1,26 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others. 
+ * All rights reserved.   This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v0.5 
+ * which accompanies this distribution, and is available at 
+ * http://www.eclipse.org/legal/cpl-v05. html
+ *
+ * Contributors: 
+ * Rational Software - Initial API and implementation
+ *
+***********************************************************************/
+
+
 package org.eclipse.cdt.internal.core.parser;
 
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
 import java.util.Stack;
+
 /**
  * @author aniefer
  *
@@ -9,6 +29,7 @@
  * To enable and disable the creation of type comments go to
  * Window>Preferences>Java>Code Generation.
  */
+
 public class ParserSymbolTable {
 
 	/**
@@ -21,8 +42,10 @@
 	}
 
 	public void push( Declaration obj ){
-		if( _contextStack.empty() == false )
+		if( _contextStack.empty() == false && obj.getContainingScope() == null ){
 			obj.setContainingScope( (Declaration) _contextStack.peek() );
+		}
+		
 		_contextStack.push( obj );
 	}
 	
@@ -34,22 +57,589 @@
 		return (Declaration) _contextStack.peek();
 	}
 	
+	public Declaration getCompilationUnit(){
+			return _compilationUnit;
+	}
+		
 	public Declaration Lookup( String name ) throws ParserSymbolTableException {
-		return ( (Declaration) _contextStack.peek() ).Lookup( -1, name );
+		LookupData data = new LookupData( name, -1 );
+		return Lookup( data, (Declaration) _contextStack.peek() );
 	}
 	
 	public Declaration ElaboratedLookup( int type, String name ) throws ParserSymbolTableException{
-		return ( (Declaration) _contextStack.peek() ).Lookup( type, name );
+		LookupData data = new LookupData( name, type );
+		return Lookup( data, (Declaration) _contextStack.peek() );
 	}
+
+	/**
+	 * Method LookupNestedNameSpecifier.
+	 * @param name
+	 * @return Declaration
+	 * The name of a class or namespace member can be referred to after the ::
+	 * scope resolution operator applied to a nested-name-specifier that
+	 * nominates its class or namespace.  During the lookup for a name preceding
+	 * the ::, object, function and enumerator names are ignored.  If the name
+	 * is not a class-name or namespace-name, the program is ill-formed
+	 */
 	
-	public void addDeclaration( Declaration obj ){
-		((Declaration) _contextStack.peek() ).addDeclaration( obj );
+	public Declaration LookupNestedNameSpecifier( String name ) throws ParserSymbolTableException {
+		return LookupNestedNameSpecifier( name, (Declaration) _contextStack.peek() );
+	}
+
+	private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException 
+	{		
+		Declaration foundDeclaration = null;
+		
+		LookupData data = new LookupData( name, Declaration.t_namespace );
+		data.upperType = Declaration.t_union;
+		
+		foundDeclaration = LookupInContained( data, inDeclaration );
+			
+		if( foundDeclaration == null && inDeclaration._containingScope != null ){
+			foundDeclaration = LookupNestedNameSpecifier( name, inDeclaration._containingScope );
+		}
+			
+		return foundDeclaration;
 	}
 	
-	public Declaration getCompilationUnit(){
-		return _compilationUnit;
+	/**
+	 * 
+	 * @param name
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 * 
+	 * During lookup for a name preceding the :: scope resolution operator,
+	 * object, function, and enumerator names are ignored.
+	 */
+	public Declaration QualifiedLookup( String name ) throws ParserSymbolTableException
+	{
+		LookupData data = new LookupData( name, -1 );
+		data.qualified = true;
+		return Lookup( data, (Declaration) _contextStack.peek() );
+	}
+	
+	public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException 
+	{
+		if( namespace.getType() != Declaration.t_namespace ){
+			throw new ParserSymbolTableException();
+		}
+			
+		Declaration declaration = (Declaration) _contextStack.peek();
+		
+		if( declaration._usingDirectives == null ){
+			declaration._usingDirectives = new LinkedList(); 
+		}
+		
+		declaration._usingDirectives.add( namespace );
+	}
+	
+	public void addDeclaration( Declaration obj ) throws ParserSymbolTableException{
+		Declaration containing = (Declaration) _contextStack.peek();
+		Map declarations = containing.getContainedDeclarations();
+		
+		Object origObj = null;
+		
+		obj.setContainingScope( containing );
+
+		if( declarations == null ){
+			declarations = containing.createContained();
+		} else {
+			//does this name exist already?
+			origObj = declarations.get( obj.getName() );
+		}
+		
+		if( origObj != null )
+		{
+			Declaration origDecl = null;
+			LinkedList  origList = null;
+		
+			if( origObj.getClass() == Declaration.class ){
+				origDecl = (Declaration)origObj;
+			} else if( origObj.getClass() == LinkedList.class ){
+				origList = (LinkedList)origObj;
+			} else {
+				throw new ParserSymbolTableException();
+			}
+			
+			if( (origList == null) ? isValidOverload( origDecl, obj ) : isValidOverload( origList, obj ) ){
+				if( origList == null ){
+					origList = new LinkedList();
+					origList.add( origDecl );
+					origList.add( obj );
+				
+					declarations.remove( obj );
+					declarations.put( obj.getName(), origList );
+				} else	{
+					origList.add( obj );
+					//origList is already in _containedDeclarations
+				}
+			} else {
+				throw new ParserSymbolTableException();
+			}
+		} else {
+			declarations.put( obj.getName(), obj );
+		}
+	}
+	
+	/**
+	 * Lookup the name from LookupData starting in the inDeclaration
+	 * @param data
+	 * @param inDeclaration
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 */
+	static private Declaration Lookup( LookupData data, Declaration inDeclaration ) throws ParserSymbolTableException
+	{
+		if( data.type != -1 && data.type < Declaration.t_class && data.upperType > Declaration.t_union ){
+			throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
+		}
+		
+		Declaration decl = null;					//the return value
+		LinkedList tempList = null;
+		LinkedList foundNames = new LinkedList();	//list of names found
+		LinkedList transitives = new LinkedList();	//list of transitive using directives
+		
+		
+		//if this name define in this scope?
+		decl = LookupInContained( data, inDeclaration );
+		if( decl != null ){
+			foundNames.add( decl );		 
+		}
+			
+		//check nominated namespaces
+		//the transitives list is populated in LookupInNominated, and then 
+		//processed in ProcessDirectives
+		
+		data.visited.clear(); //each namesapce is searched at most once, so keep track
+		
+		tempList = LookupInNominated( data, inDeclaration, transitives );
+				
+		if( tempList != null ){
+			foundNames.addAll( tempList );
+		}
+			
+		//if we are doing a qualified lookup, only process using directives if
+		//we haven't found the name yet. 
+		if( !data.qualified || foundNames.size() == 0 ){
+			ProcessDirectives( inDeclaration, data, transitives );
+			
+			if( inDeclaration._usingDirectives != null ){
+				ProcessDirectives( inDeclaration, data, inDeclaration._usingDirectives );
+			}
+						
+			while( data.usingDirectives != null && data.usingDirectives.get( inDeclaration ) != null ){
+				transitives.clear();
+				
+				tempList = LookupInNominated( data, inDeclaration, transitives );
+				
+				if( tempList != null ){
+					foundNames.addAll( tempList );
+				}
+
+				if( !data.qualified || foundNames.size() == 0 ){
+					ProcessDirectives( inDeclaration, data, transitives );
+				}
+			}
+		}
+		
+		decl = ResolveAmbiguities( foundNames );
+		if( decl != null ){
+			return decl;
+		}
+			
+		//if we still havn't found it, check any parents we have
+		data.visited.clear();	//each virtual base class is searched at most once	
+		decl = LookupInParents( data, inDeclaration );	
+					
+		//if still not found, check our containing scope.			
+		if( decl == null && inDeclaration._containingScope != null ){ 
+			decl = Lookup( data, inDeclaration._containingScope );
+		}
+
+		return decl;
+	}
+	
+	/**
+	 * function LookupInNominated
+	 * @param data
+	 * @param transitiveDirectives
+	 * @return List
+	 * 
+	 * for qualified:
+	 *  3.4.3.2-2 "let S be the set of all declarations of m in X
+	 * and in the transitive closure of all namespaces nominated by using-
+	 * directives in X and its used namespaces, except that using-directives are
+	 * ignored in any namespace, including X, directly containing one or more
+	 * declarations of m."
+	 * 
+	 * for unqualified:
+	 * 7.3.4-2 The using-directive is transitive: if a scope contains a using
+	 * directive that nominates a second namespace that itself contains using-
+	 * directives, the effect is as if the using-directives from the second
+	 * namespace also appeared in the first.
+	 */
+	static private LinkedList LookupInNominated( LookupData data, Declaration declaration, LinkedList transitiveDirectives ) throws ParserSymbolTableException{
+		//if the data.usingDirectives is empty, there is nothing to do.
+		if( data.usingDirectives == null ){
+			return null;
+		}
+			
+		LinkedList found = null;	//list of found names to return
+		
+		//local variables
+		LinkedList  list = null;
+		Iterator    iter = null;
+		Declaration decl = null;
+		Declaration temp = null;
+		int size = 0;
+		
+		list = (LinkedList) data.usingDirectives.remove( declaration );
+		
+		if( list == null ){
+			return null;
+		}
+		
+		iter = list.iterator();
+		size = list.size();
+		for( int i = size; i > 0; i-- ){
+			decl = (Declaration) iter.next();
+
+			//namespaces are searched at most once
+			if( !data.visited.contains( decl ) ){
+				data.visited.add( decl );
+				
+				temp = LookupInContained( data, decl );
+										
+				//if we found something, add it to the list of found names
+				if( temp != null ){
+					if( found == null ){ 
+						found = new LinkedList();
+					}
+					found.add( temp );
+				}	
+				
+				//only consider the transitive using directives if we are an unqualified
+				//lookup, or we didn't find the name in decl
+				if( (!data.qualified || temp == null) && decl._usingDirectives != null ){
+					//name wasn't found, add transitive using directives for later consideration
+					transitiveDirectives.addAll( decl._usingDirectives );
+				}
+			}
+		}
+		
+		return found;
+	}
+	
+	/**
+	 * function LookupInContained
+	 * @param data
+	 * @return List
+	 * @throws ParserSymbolTableException
+	 * 
+	 * Look for data.name in our collection _containedDeclarations
+	 */
+	private static Declaration LookupInContained( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
+		LinkedList found = null;
+		Declaration temp  = null;
+		Object obj = null;
+	
+		Map declarations = lookIn.getContainedDeclarations();
+		if( declarations == null )
+			return null;
+		
+		obj = declarations.get( data.name );
+	
+		if( obj == null ){
+			//not found
+			return null;
+		}
+			
+	 	//the contained declarations map either to a Declaration object, or to a list
+	 	//of declaration objects.
+		if( obj.getClass() == Declaration.class ){	
+			if( ((Declaration)obj).isType( data.type, data.upperType ) ){
+				return (Declaration) obj;
+			}
+		} else {
+			found = new LinkedList();
+			
+			LinkedList objList = (LinkedList)obj;
+			Iterator iter  = objList.iterator();
+			int size = objList.size();
+					
+			for( int i = 0; i < size; i++ ){
+				temp = (Declaration) iter.next();
+		
+				if( temp.isType( data.type, data.upperType ) ){
+					found.add(temp);
+				} 
+			}
+		}
+
+		//if none of the found items made it through the type filtering, just
+		//return null instead of an empty list.
+		if( found == null || found.size() == 0 )			
+			return null;
+		
+		return ResolveAmbiguities( found );
+	}
+	
+	/**
+	 * 
+	 * @param data
+	 * @param lookIn
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 */
+	private static Declaration LookupInParents( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
+		LinkedList scopes = lookIn.getParentScopes();
+		Declaration decl = null;
+		Declaration temp = null;
+		Iterator iterator = null;
+		Declaration.ParentWrapper wrapper = null;
+		
+		if( scopes == null )
+			return null;
+				
+		iterator = scopes.iterator();
+			
+		int size = scopes.size();
+	
+		for( int i = size; i > 0; i-- )
+		{
+			wrapper = (Declaration.ParentWrapper) iterator.next();
+			if( !wrapper.isVirtual || !data.visited.contains( wrapper.parent ) ){
+				if( wrapper.isVirtual ){
+					data.visited.add( wrapper.parent );
+				}
+				
+				//is this name define in this scope?
+				temp =  LookupInContained( data, wrapper.parent );
+					
+				if( temp == null ){
+					temp = LookupInParents( data, wrapper.parent );
+				}
+			}	
+			
+			if( temp != null && temp.isType( data.type ) ){
+				if( decl == null  ){
+					decl = temp;
+				} else if ( temp != null ) {
+					//it is not ambiguous if temp & decl are the same thing and it is static
+					//or an enumerator
+					if( decl == temp && ( temp.isStatic() || temp.getType() == Declaration.t_enumerator) ){
+						temp = null;
+					} else {
+						throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) );
+					}
+	
+				}
+			} else {
+				temp = null;	//reset temp for next iteration
+			}
+		}
+	
+		return decl;	
+	}
+	
+	/**
+	 * function isValidOverload
+	 * @param origDecl
+	 * @param newDecl
+	 * @return boolean
+	 * 
+	 * 3.3.7 "A class name or enumeration name can be hidden by the name of an
+	 * object, function or enumerator declared in the same scope"
+	 * 
+	 * 3.4-1 "Name lookup may associate more than one declaration with a name if
+	 * it finds the name to be a function name"
+	 */
+	private static boolean isValidOverload( Declaration origDecl, Declaration newDecl ){
+		int origType = origDecl.getType();
+		int newType  = newDecl.getType();
+		
+		if( (origType >= Declaration.t_class && origType <= Declaration.t_enum) && //class name or enumeration ...
+			( newType == Declaration.t_type || (newType >= Declaration.t_function && newType <= Declaration.typeMask) ) ){
+				
+			return true;
+		}
+		//if the origtype is not a class-name or enumeration name, then the only other
+		//allowable thing is if they are both functions.
+		else if( origType == Declaration.t_function && newType == Declaration.t_function ){
+			return true;
+		}
+		
+		return false;
+	}
+	
+	private static boolean isValidOverload( LinkedList origList, Declaration newDecl ){
+		if( origList.size() == 1 ){
+			return isValidOverload( (Declaration)origList.getFirst(), newDecl );
+		} else if ( origList.size() > 1 ){
+
+			//the first thing can be a class-name or enumeration name, but the rest
+			//must be functions.  So make sure the newDecl is a function before even
+			//considering the list
+			if( newDecl.getType() != Declaration.t_function ){
+				return false;
+			}
+			
+			Iterator iter = origList.iterator();
+			Declaration decl = (Declaration) iter.next();
+			boolean valid = (( decl.getType() >= Declaration.t_class && decl.getType() <= Declaration.t_enum ) ||
+							  decl.getType() == Declaration.t_function );
+			
+			while( valid && iter.hasNext() ){
+				decl = (Declaration) iter.next();
+				valid = ( decl.getType() == Declaration.t_function );
+			}
+			
+			return valid;
+		}
+		
+		//empty list, return true
+		return true;
+	}
+	
+	static private Declaration ResolveAmbiguities( LinkedList items ) throws ParserSymbolTableException{
+		Declaration decl = null;
+	
+		int size = items.size(); 
+	
+		if( size == 0){
+			return null;
+		} else if (size == 1) {
+			return (Declaration) items.getFirst();
+		} else	{
+			Declaration first  = (Declaration)items.removeFirst();
+	
+			//if first one is a class-name, the next ones hide it
+			if( first.getType() >= Declaration.t_class && first.getType() <= Declaration.t_enum ){
+				return ResolveAmbiguities( items );
+			}
+		
+			//else, if the first is an object (ie not a function), the rest must be the same
+			//declaration.  otherwise (ie it is a function), the rest must be functions.
+			boolean needSame = ( first.getType() != Declaration.t_function );
+	
+			Iterator iter = items.iterator();
+		
+			for( int i = (size - 1); i > 0; i-- ){
+				decl = (Declaration) iter.next();
+			
+				if( needSame ){
+					if( decl != first ){
+						throw new ParserSymbolTableException();
+					}
+				} else {
+					if( decl.getType() != Declaration.t_function ){
+						throw new ParserSymbolTableException();
+					}
+				}
+			}
+		
+			if( needSame ){
+				return first;
+			} else {
+				items.addFirst( first );
+				return ResolveFunction( items );
+			}
+		}
+	}
+
+	static private Declaration ResolveFunction( LinkedList functions ){
+		//TBD
+		return null;
+	}
+	
+	/**
+	 * function ProcessDirectives
+	 * @param Declaration decl
+	 * @param LookupData  data
+	 * @param LinkedList  directives
+	 * 
+	 * Go through the directives and for each nominated namespace find the
+	 * closest enclosing declaration for that namespace and decl, then add the
+	 * nominated namespace to the lookup data for consideration when we reach
+	 * the enclosing declaration.
+	 */
+	static private void ProcessDirectives( Declaration decl, LookupData data, LinkedList directives ){
+		Declaration enclosing = null;
+		Declaration temp = null;
+		
+		int size = directives.size();
+		Iterator iter = directives.iterator();
+	
+		for( int i = size; i > 0; i-- ){
+			temp = (Declaration) iter.next();
+		
+			//namespaces are searched at most once
+			if( !data.visited.contains( temp ) ){
+				enclosing = getClosestEnclosingDeclaration( decl, temp );
+						
+				//the data.usingDirectives is a map from enclosing declaration to 
+				//a list of namespaces to consider when we reach that enclosing
+				//declaration
+				LinkedList list = (data.usingDirectives == null ) 
+								? null
+								: (LinkedList) data.usingDirectives.get( enclosing );
+				if ( list == null ){
+					list = new LinkedList();
+					list.add( temp );
+					if( data.usingDirectives == null ){
+						data.usingDirectives = new HashMap();
+					}
+					data.usingDirectives.put( enclosing, list );
+				} else {
+					list.add( temp );
+				}
+			}
+		}
+	}
+	
+	/**
+	 * function getClosestEnclosingDeclaration
+	 * @param decl1
+	 * @param decl2
+	 * @return Declaration
+	 * 
+	 * 7.3.4-1 "During unqualified lookup, the names appear as if they were
+	 * declared in the nearest enclosing namespace which contains both the
+	 * using-directive and the nominated namespace"
+	 * 
+	 * TBD: Consider rewriting this iteratively instead of recursively, for
+	 * performance
+	 */
+	static private Declaration getClosestEnclosingDeclaration( Declaration decl1, Declaration decl2 ){
+		if( decl1 == decl2 ){ 
+			return decl1;
+		}
+				
+		if( decl1._depth == decl2._depth ){
+			return getClosestEnclosingDeclaration( decl1._containingScope, decl2._containingScope );
+		} else if( decl1._depth > decl2._depth ) {
+			return getClosestEnclosingDeclaration( decl1._containingScope, decl2 );
+		} else {
+			return getClosestEnclosingDeclaration( decl1, decl2._containingScope );
+		}
 	}
 	
 	private Stack _contextStack = new Stack();
 	private Declaration _compilationUnit;
+	
+	private class LookupData
+	{
+		public String name;
+		public Map usingDirectives; 
+		public Set visited = new HashSet();	//used to ensure we don't visit things more than once
+		
+		public int type = -1;
+		public int upperType = 0;
+		public boolean qualified = false;
+
+		public LookupData( String n, int t ){
+			name = n;
+			type = t;
+		}
+	}
 }
Index: parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java,v
retrieving revision 1.2
diff -u -r1.2 ParserSymbolTableException.java
--- parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java	4 Mar 2003 18:25:40 -0000	1.2
+++ parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java	5 Mar 2003 22:55:31 -0000
@@ -1,3 +1,14 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
 package org.eclipse.cdt.internal.core.parser;
 
 /**
Index: parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java,v
retrieving revision 1.2
diff -u -r1.2 ParserSymbolTableTest.java
--- parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	4 Mar 2003 18:25:44 -0000	1.2
+++ parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	5 Mar 2003 22:56:08 -0000
@@ -1,3 +1,14 @@
+/**********************************************************************
+ * Copyright (c) 2002,2003 Rational Software Corporation and others.
+ * All rights reserved.   This program and the accompanying materials
+ * are made available under the terms of the Common Public License v0.5
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v05.html
+ * 
+ * Contributors: 
+ * Rational Software - Initial API and implementation
+***********************************************************************/
+
 package org.eclipse.cdt.core.parser.tests;
 
 import junit.framework.TestCase;
@@ -333,7 +344,7 @@
 		table.addDeclaration( d );
 		
 		Declaration enum = new Declaration("enum");
-		enum.setType( Declaration.t_enum );
+		enum.setType( Declaration.t_enumerator );
 		
 		Declaration stat = new Declaration("static");
 		stat.setStatic(true);
@@ -496,5 +507,519 @@
 		//notice that, with the current implementation, you can't do a lookup
 		//on just the function name without the rest of the signature
 		assertEquals( table.Lookup("foo"), null );
+	}
+	
+	/**
+	 * 
+	 * @throws Exception
+	 * 
+	 * 	struct stat {
+	 * 		//...
+	 *  }
+	 *  int stat( struct stat* );
+	 *  void f() 
+	 *  {
+	 *  	struct stat *ps;
+	 *   	stat(ps);
+	 *  }
+	 */
+	public void testFunctionHidesClass() throws Exception{
+		newTable();
+		
+		Declaration struct = new Declaration( "stat");
+		struct.setType( Declaration.t_struct );
+		table.addDeclaration( struct );
+		
+		Declaration function = new Declaration( "stat" );
+		function.setType( Declaration.t_function );
+		table.addDeclaration( function );
+		
+		Declaration f = new Declaration("f");
+		f.setType( Declaration.t_function );
+		table.addDeclaration( f );
+		table.push( f );
+		
+		Declaration look = table.ElaboratedLookup( Declaration.t_struct, "stat" );
+		assertEquals( look, struct );
+		
+		look = table.Lookup( "stat" );
+		assertEquals( look, function );
+	}
+	
+	/**
+	 * 
+	 * @throws Exception
+	 * 
+	 * namespace A {
+	 *    int i;
+	 *    namespace B {
+	 *       namespace C{
+	 *          int i;
+	 *       }
+	 *       using namespace A::B::C;
+	 *       void f1() {
+	 *          i = 5;  //OK, C::i visible and hides A::i
+	 *       }
+	 *    }
+	 *    namespace D{
+	 *       using namespace B;
+	 *       using namespace C;
+	 *       void f2(){
+	 *          i = 5;  //ambiguous, B::C and A::i
+	 *       }
+	 *    }
+	 *    void f3() {
+	 *       i = 5;   //uses A::i
+	 *    }
+	 * }
+	 * void f4(){
+	 *    i = 5;   //no i is visible here 
+	 * }
+	 * 
+	 */
+	public void testUsingDirectives_1() throws Exception{
+		newTable();
+		
+		Declaration nsA = new Declaration("A");
+		nsA.setType( Declaration.t_namespace );
+		table.addDeclaration( nsA );
+		table.push( nsA );
+		
+		Declaration nsA_i = new Declaration("i");
+		table.addDeclaration( nsA_i );
+		
+		Declaration nsB = new Declaration("B");
+		nsB.setType( Declaration.t_namespace );
+		table.addDeclaration( nsB );
+		table.push( nsB );
+		
+		Declaration nsC = new Declaration("C");
+		nsC.setType( Declaration.t_namespace );
+		table.addDeclaration( nsC );
+		table.push( nsC );
+		
+		Declaration nsC_i = new Declaration("i");
+		table.addDeclaration( nsC_i );
+		table.pop();
+		
+		Declaration look = table.Lookup("C");
+		table.addUsingDirective( look );
+		
+		Declaration f1 = new Declaration("f");
+		f1.setType( Declaration.t_function );
+		table.push( f1 );
+		
+		look = table.Lookup( "i" );
+		assertEquals( look, nsC_i ); //C::i visible and hides A::i
+		
+		table.pop();  //end of f1
+		table.pop();  //end of nsB
+		
+		assertEquals( table.peek(), nsA );
+		
+		Declaration nsD = new Declaration("D");
+		nsD.setType( Declaration.t_namespace );
+		table.addDeclaration( nsD );
+		table.push( nsD );
+		
+		look = table.Lookup("B");
+		assertEquals( look, nsB );
+		table.addUsingDirective( look );
+		
+		look = table.Lookup("C");
+		assertEquals( look, nsC );
+		table.addUsingDirective( look );
+		
+		Declaration f2 = new Declaration( "f2" );
+		f2.setType( Declaration.t_function );
+		table.addDeclaration( f2 );
+		table.push( f2 );
+		
+		try
+		{
+			look = table.Lookup( "i" );
+			assertTrue( false );
+		}
+		catch ( ParserSymbolTableException e )
+		{
+			assertTrue(true); //ambiguous B::C::i and A::i
+		}
+		table.pop(); //end f2
+		table.pop(); //end nsD
+		
+		Declaration f3 = new Declaration ("f3");
+		f3.setType( Declaration.t_function );
+		table.addDeclaration( f3 );
+		table.push( f3 );
+		
+		look = table.Lookup("i");
+		assertEquals( look, nsA_i );  //uses A::i
+		
+		table.pop();
+		table.pop();
+		
+		Declaration f4 = new Declaration ("f4");
+		f4.setType( Declaration.t_function );
+		table.addDeclaration( f4 );
+		table.push( f4 );
+		
+		look = table.Lookup("i");
+		assertEquals( look, null );//neither i is visible here.
+	}
+	/**
+	 * 
+	 * @throws Exception
+	 * 
+	 * namespace M {
+	 *    int i;
+	 * }
+	 * namespace N {
+	 *    int i;
+	 *    using namespace M;
+	 * }
+	 * 
+	 * void f() {
+	 *    using namespace N;
+	 *    i = 7;           //error, both M::i and N::i are visible
+	 *    N::i = 5;        //ok, i directly declared in N, using M not
+	 *                       considered (since this is a qualified lookup)
+	 * }
+	 * 
+	 */
+	public void testTransitiveUsingDirective() throws Exception
+	{
+		newTable();
+		
+		Declaration nsM = new Declaration( "M" );
+		nsM.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( nsM );
+		
+		table.push( nsM );
+		Declaration nsM_i = new Declaration("i");
+		table.addDeclaration( nsM_i );
+		table.pop();
+		
+		Declaration nsN = new Declaration( "N" );
+		nsN.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( nsN );
+		
+		table.push( nsN );
+		Declaration nsN_i = new Declaration("i");
+		table.addDeclaration( nsN_i );
+		table.addUsingDirective( nsM );
+		table.pop();
+		
+		Declaration f = new Declaration("f");
+		table.addDeclaration( f );
+		table.push( f );
+		
+		table.addUsingDirective( nsN );
+		
+		Declaration look = null;
+		try
+		{
+			look = table.Lookup( "i" );
+			assertTrue( false );
+		}
+		catch ( ParserSymbolTableException e )
+		{
+			assertTrue( true );		//ambiguous, both M::i and N::i are visible.
+		}
+		
+		look = table.LookupNestedNameSpecifier("N");
+		table.push( look );
+		look = table.QualifiedLookup("i"); //ok
+		assertEquals( look, nsN_i );
+	}
+	
+	/**
+	 * 
+	 * @throws Exception
+	 * The same declaration found more than once is not an ambiguity
+	 * namespace A{
+	 *    int a;
+	 * }
+	 * namespace B{
+	 *    using namespace A;
+	 * }
+	 * namespace C{
+	 *    using namespace A;
+	 * }
+	 * 
+	 * namespace BC{
+	 *    using namespace B;
+	 *    using namespace C;
+	 * }
+	 * 
+	 * void f(){
+	 *    BC::a++; //ok 
+	 * }
+	 */
+	public void testUsing_SameDeclarationTwice() throws Exception
+	{
+		newTable();
+		
+		Declaration nsA = new Declaration("A");
+		nsA.setType( Declaration.t_namespace );
+		table.addDeclaration( nsA );
+		table.push( nsA );
+		
+		Declaration a = new Declaration("a");
+		table.addDeclaration( a );
+		table.pop();
+		
+		Declaration nsB = new Declaration("B");
+		nsB.setType( Declaration.t_namespace );
+		table.addDeclaration( nsB );
+		table.push( nsB );
+		table.addUsingDirective( nsA );
+		table.pop();
+
+		Declaration nsC = new Declaration("C");
+		nsC.setType( Declaration.t_namespace );
+		table.addDeclaration( nsC );
+		table.push( nsC );
+		table.addUsingDirective( nsA );
+		table.pop();	
+		
+		Declaration nsBC = new Declaration("BC");
+		nsBC.setType( Declaration.t_namespace );
+		table.addDeclaration( nsBC );
+		table.push( nsBC );
+		table.addUsingDirective( nsB );
+		table.addUsingDirective( nsC );		
+		table.pop();
+		
+		Declaration f = new Declaration("f");
+		f.setType(Declaration.t_function);
+		table.addDeclaration( f );
+		table.push(f);
+		
+		Declaration look = table.LookupNestedNameSpecifier("BC");
+		assertEquals( look, nsBC );
+		table.push(look);
+		look = table.QualifiedLookup("a");
+		assertEquals( look, a );
+	}
+	
+	/**
+	 * 
+	 * @throws Exception
+	 * 
+	 * namespace B {
+	 *    int b;
+	 * }
+	 * namespace A {
+	 *    using namespace B;
+	 *    int a;
+	 * }
+	 * namespace B {
+	 *    using namespace A;
+	 * }
+	 * 
+	 * void f(){
+	 *    A::a++;   //ok
+	 *    A::b++;   //ok
+	 *    B::a++;   //ok       
+	 *    B::b++;   //ok 
+	 * }
+	 */
+	public void testUsing_SearchedOnce() throws Exception
+	{
+		newTable();
+		
+		Declaration nsB = new Declaration( "B" );
+		nsB.setType( Declaration.t_namespace );
+		table.addDeclaration( nsB );
+		table.push( nsB );
+		
+		Declaration b = new Declaration("b");
+		table.addDeclaration( b );
+		table.pop();
+		
+		Declaration nsA = new Declaration( "A" );
+		nsA.setType( Declaration.t_namespace );
+		table.addDeclaration( nsA );
+		table.push( nsA );
+		
+		table.addUsingDirective( nsB );
+		
+		Declaration a = new Declaration("a");
+		table.addDeclaration( a );
+		
+		table.pop();
+		
+		table.push( nsB );
+		table.addUsingDirective( nsA );
+		table.pop();
+		
+		Declaration f = new Declaration("f");
+		table.addDeclaration(f);
+		table.push(f);
+		
+		Declaration look = table.LookupNestedNameSpecifier("A");
+		table.push(look);
+		look = table.QualifiedLookup("a");
+		assertEquals( look, a );
+		
+		look = table.QualifiedLookup("b");
+		assertEquals( look, b );
+		table.pop();
+		
+		look = table.LookupNestedNameSpecifier("B");
+		table.push(look);
+		look = table.QualifiedLookup("a");
+		assertEquals( look, a );
+		
+		look = table.QualifiedLookup("b");
+		assertEquals( look, b );
+		table.pop();
+		 
+	}
+	
+	/**
+	 * we pass if we don't go into an infinite loop.
+	 * TBD: we need a mechanism to detect failure of this
+	 * test instead of just looping forever.
+	 * 
+	 * @throws Exception
+	 * 
+	 * namespace A{
+	 * }
+	 * namespace B{
+	 *    using namespace A;
+	 * }
+	 * namespace A{
+	 *    using namespace B;
+	 * }
+	 * void f(){
+	 *    using namespace A;
+	 *    using namespace B;
+	 *    i = 1; //not declared anywhere.
+	 * }
+	 */
+	public void testUsing_SearchedOnce_2() throws Exception
+	{
+		newTable();
+		
+		Declaration nsA = new Declaration( "A" );
+		nsA.setType( Declaration.t_namespace );
+		table.addDeclaration( nsA );
+			
+		Declaration nsB = new Declaration( "B" );
+		nsB.setType( Declaration.t_namespace );
+		table.addDeclaration( nsB );
+		table.push( nsB );
+		table.addUsingDirective( nsA );
+		table.pop();
+		
+		table.push( nsA );
+		table.addUsingDirective( nsB );
+		table.pop();
+
+		Declaration f = new Declaration("f");
+		table.addDeclaration(f);
+		table.push(f);
+		table.addUsingDirective(nsA);
+		table.addUsingDirective(nsB);
+		
+		Declaration look = table.Lookup("i");
+		assertEquals( look, null );
+		
+	}
+	
+	/**
+	 * During lookup of a qualified namespace member name, if the lookup finds
+	 * more than one declaration of the member, non-type names hide class or
+	 * enumeration names if and only if the declarations are from the same
+	 * namespace
+	 * @throws Exception
+	 * 
+	 * namespace A {
+	 *    struct x { };
+	 *    int x;
+	 *    int y;
+	 * }
+	 * namespace B {
+	 *    struct y { };
+	 * }
+	 * 
+	 * namespace C {
+	 *    using namespace A;
+	 *    using namespace B;
+	 * 
+	 *    int i = C::x;      //ok, finds A::x
+	 *    int j = C::y;      //ambiguous, A::y or B::y
+	 * }
+	 */
+	public void testNamespaceMemberHiding() throws Exception{
+		newTable();
+		
+		Declaration nsA = new Declaration("A");
+		nsA.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( nsA );
+		table.push( nsA );
+		
+		Declaration structX = new Declaration("x");
+		structX.setType( Declaration.t_struct );
+		table.addDeclaration( structX );
+		
+		Declaration intX = new Declaration("x");
+		intX.setType( Declaration.t_int );
+		table.addDeclaration( intX );
+		
+		Declaration intY = new Declaration("y");
+		intY.setType( Declaration.t_int );
+		table.addDeclaration( intY );
+
+		table.pop();
+		
+		Declaration nsB = new Declaration("B");
+		nsB.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( nsB );
+		table.push( nsB );
+		
+		Declaration structY = new Declaration("y");
+		structY.setType( Declaration.t_struct );
+		table.addDeclaration( structY );
+		
+		table.pop();
+		
+		Declaration nsC = new Declaration("C");
+		nsC.setType( Declaration.t_namespace);
+		table.addDeclaration( nsC );
+		
+		table.push( nsC );
+		
+		Declaration look = table.Lookup("A");
+		assertEquals( look, nsA );
+		table.addUsingDirective( look );
+		
+		look = table.Lookup("B");
+		assertEquals( look, nsB );
+		table.addUsingDirective( look );
+		
+		//lookup C::x
+		look = table.LookupNestedNameSpecifier("C");
+		assertEquals( look, nsC );
+		table.push(look);
+		look = table.QualifiedLookup( "x" );
+		assertEquals( look, intX );
+		table.pop();
+		
+		//lookup C::y
+		look = table.LookupNestedNameSpecifier("C");
+		assertEquals( look, nsC );
+		table.push(look);
+		try{
+			look = table.QualifiedLookup( "y" );
+			assertTrue(false);
+		} catch ( Exception e ) {
+			assertTrue(true);
+		}
 	}
 }

Back to the top