Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Parser Symbol Table updates

Patch for the parser's symbol table.
-friends
-"this" pointer
-enumerators
-argument dependent lookup
-function parameters & function overloading

attached are:
patch_03.20.03(cdt.core).txt		(changes)
patch_03.20.03(cdt.ui.tests).txt	(junit tests)

-Andrew

Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/ChangeLog,v
retrieving revision 1.6
diff -u -r1.6 ChangeLog
--- ChangeLog	20 Mar 2003 15:13:09 -0000	1.6
+++ ChangeLog	20 Mar 2003 22:22:12 -0000
@@ -1,3 +1,11 @@
+2003-03-20 Andrew Niefer
+	Parser Symbol Table updates for:
+	* friends
+	* "this" pointer
+	* enumerators
+	* Argument dependent lookup
+	* adding parameters to functions & function overloading
+	
 2003-03-19	John Camelon
 	Updated Parser method visibility to solidify external interface.  
 	Solved and removed TODO's from Scanner implementation.
Index: 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.3
diff -u -r1.3 Declaration.java
--- org/eclipse/cdt/internal/core/parser/Declaration.java	6 Mar 2003 18:42:26 -0000	1.3
+++ org/eclipse/cdt/internal/core/parser/Declaration.java	20 Mar 2003 22:22:13 -0000
@@ -14,6 +14,7 @@
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.Iterator;
 
 /**
  * @author aniefer
@@ -24,7 +25,7 @@
  * Window>Preferences>Java>Code Generation.
  */
 
-public class Declaration {
+public class Declaration implements Cloneable {
 
 	/**
 	 * Constructor for Declaration.
@@ -42,6 +43,40 @@
 		_object = obj;
 	}
 
+	/**
+	 * clone
+	 * @see java.lang.Object#clone()
+	 * 
+	 * implement clone for the purposes of using declarations.
+	 * int   		_typeInfo;				//by assignment
+	 * String 		_name;					//by assignment
+	 * Object 		_object;				//null this out
+	 * Declaration	_typeDeclaration;		//by assignment
+	 * Declaration	_containingScope;		//by assignment
+	 * LinkedList 	_parentScopes;			//shallow copy
+	 * LinkedList 	_usingDirectives;		//shallow copy
+	 * HashMap		_containedDeclarations;	//shallow copy
+	 * int 			_depth;					//by assignment
+	 */
+	public Object clone(){
+		Declaration copy = null;
+		try{
+			copy = (Declaration)super.clone();
+		}
+		catch ( CloneNotSupportedException e ){
+			//should not happen
+			return null;
+		}
+		
+		copy._object = null;
+		copy._parentScopes          = ( _parentScopes != null ) ? (LinkedList) _parentScopes.clone() : null;
+		copy._usingDirectives       = ( _usingDirectives != null ) ? (LinkedList) _usingDirectives.clone() : null; 
+		copy._containedDeclarations = ( _containedDeclarations != null ) ? (HashMap) _containedDeclarations.clone() : null;
+		copy._parameters            = ( _parameters != null ) ? (LinkedList) _parameters.clone() : null;
+		
+		return copy;	
+	}
+	
 	public static final int typeMask   = 0x001f;
 	public static final int isAuto     = 0x0020;
 	public static final int isRegister = 0x0040;
@@ -112,7 +147,7 @@
 	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_enumeration =  5;
 	public static final int t_function    =  6;
 	public static final int t_char        =  7;
 	public static final int t_wchar_t     =  8;
@@ -169,13 +204,6 @@
 	}
 	
 	public void setTypeDeclaration( Declaration type ){
-		//setting our type to a declaration implies we are type t_type
-		try { 
-			setType( t_type ); 
-		} catch (ParserSymbolTableException e) { 
-			/*will never happen*/ 
-		}
-		
 		_typeDeclaration = type; 
 	}
 	
@@ -217,6 +245,93 @@
 		return _parentScopes;
 	}
 	
+	public boolean needsDefinition(){
+		return _needsDefinition;
+	}
+	public void setNeedsDefinition( boolean need ) {
+		_needsDefinition = need;
+	}
+	
+	public String getCVQualifier(){
+		return _cvQualifier;
+	}
+	
+	public void setCVQualifier( String cv ){
+		_cvQualifier = cv;
+	}
+	
+	public String getPtrOperator(){
+		return _ptrOperator;
+	}
+	public void setPtrOperator( String ptrOp ){
+		_ptrOperator = ptrOp;
+	}
+	
+	public int getReturnType(){
+		return _returnType;
+	}
+	
+	public void setReturnType( int type ){
+		_returnType = type;
+	}
+	
+	public void addParameter( Declaration typeDecl, String ptrOperator, boolean hasDefault ){
+		if( _parameters == null ){
+			_parameters = new LinkedList();
+		}
+		
+		ParameterInfo info = new ParameterInfo();
+		info.typeInfo = t_type;
+		info.typeDeclaration = typeDecl;
+		info.ptrOperator = ptrOperator;
+		info.hasDefaultValue = hasDefault;
+				
+		_parameters.add( info );
+	}
+	
+	public void addParameter( int type, String ptrOperator, boolean hasDefault ){
+		if( _parameters == null ){
+			_parameters = new LinkedList();
+		}
+		
+		ParameterInfo info = new ParameterInfo();
+		info.typeInfo = type;
+		info.typeDeclaration = null;
+		info.ptrOperator = ptrOperator;
+		info.hasDefaultValue = hasDefault;
+				
+		_parameters.add( info );
+	}
+	
+	public boolean hasSameParameters( Declaration function ){
+		if( function.getType() != getType() ){
+			return false;	
+		}
+		
+		int size = _parameters.size();
+		if( function._parameters.size() != size ){
+			return false;
+		}
+		
+		Iterator iter = _parameters.iterator();
+		Iterator fIter = function._parameters.iterator();
+		
+		ParameterInfo info = null;
+		ParameterInfo fInfo = null;
+		
+		for( int i = size; i > 0; i-- ){
+			info = (ParameterInfo) iter.next();
+			fInfo = (ParameterInfo) fIter.next();
+			
+			if( !info.equals( fInfo ) ){
+				return false;
+			}
+		}
+		
+			
+		return true;
+	}
+	
 	// Convenience methods
 	private void setBit(boolean b, int mask){
 		if( b ){
@@ -234,11 +349,16 @@
 	private 	String 		_name;					//our name
 	private	Object 		_object;				//the object associated with us
 	private 	Declaration	_typeDeclaration;		//our type if _typeInfo says t_type
-	
+	private	boolean	_needsDefinition;		//this name still needs to be defined
+	private	String		_cvQualifier;
+	private	String		_ptrOperator;
 	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.
+	protected	HashMap 	_containedDeclarations;	//declarations contained by us.
+	
+	protected LinkedList	_parameters;			//parameter list
+	protected int			_returnType;			
 	
 	protected	int 		_depth;					//how far down the scope stack we are
 		
@@ -253,4 +373,26 @@
 		public Declaration parent = null;
 	}
 	
+	public class ParameterInfo
+	{
+		public ParameterInfo() {}
+		public ParameterInfo( int t, Declaration decl, String ptr, boolean def ){
+			typeInfo = t;
+			typeDeclaration = decl;
+			ptrOperator = ptr;
+			hasDefaultValue = def;
+		}
+		
+		public boolean equals( ParameterInfo obj ){
+			return	( hasDefaultValue == obj.hasDefaultValue ) &&
+				    ( typeInfo == obj.typeInfo ) &&
+				    ( typeDeclaration == obj.typeDeclaration ) &&
+				    ( ptrOperator.equals( obj.ptrOperator ) );
+		}
+		
+		public boolean	hasDefaultValue;
+		public int		typeInfo;
+		public Declaration	typeDeclaration;
+		public String		ptrOperator;
+	}
 }
Index: 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.3
diff -u -r1.3 ParserSymbolTable.java
--- org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	6 Mar 2003 18:42:26 -0000	1.3
+++ org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	20 Mar 2003 22:22:13 -0000
@@ -17,6 +17,7 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
@@ -38,6 +39,12 @@
 	public ParserSymbolTable() {
 		super();
 		_compilationUnit = new Declaration();
+		try{
+			_compilationUnit.setType( Declaration.t_namespace );
+		} catch ( ParserSymbolTableException e ){
+			/*shouldn't happen*/
+		}
+		
 		push( _compilationUnit );
 	}
 
@@ -86,8 +93,7 @@
 		return LookupNestedNameSpecifier( name, (Declaration) _contextStack.peek() );
 	}
 
-	private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException 
-	{		
+	private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException{		
 		Declaration foundDeclaration = null;
 		
 		LookupData data = new LookupData( name, Declaration.t_namespace );
@@ -103,25 +109,202 @@
 	}
 	
 	/**
+	 * LookupMemberForDefinition
+	 * @param name
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 * 
+	 * In a definition for a namespace member in which the declarator-id is a
+	 * qualified-id, given that the qualified-id for the namespace member has
+	 * the form "nested-name-specifier unqualified-id", the unqualified-id shall
+	 * name a member of the namespace designated by the nested-name-specifier.
+	 * 
+	 * ie:
+	 * you have this:
+	 * namespace A{    
+	 *    namespace B{       
+	 *       void  f1(int);    
+	 *    }  
+	 *    using  namespace B; 
+	 * }
+	 * 
+	 * if you then do this 
+	 * void A::f1(int) { ... } //ill-formed, f1 is not a member of A
+	 * but, you can do this (Assuming f1 has been defined elsewhere)
+	 * A::f1( 1 );  //ok, finds B::f1
+	 * 
+	 * ie, We need a seperate lookup function for looking up the member names
+	 * for a definition.
+	 */
+	public Declaration LookupMemberForDefinition( String name ) throws ParserSymbolTableException{
+		LookupData data = new LookupData( name, -1 );
+		data.qualified = true;
+	
+		return LookupInContained( data, (Declaration) _contextStack.peek() );
+	}
+	
+	/**
 	 * 
 	 * @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
-	{
+	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 
-	{
+	/**
+	 * 
+	 * @param name
+	 * @param parameters
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 */
+	public Declaration QualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+		LookupData data = new LookupData( name, Declaration.t_function );
+		data.qualified = true;
+		data.parameters = parameters;
+		
+		return Lookup( data, (Declaration) _contextStack.peek() );
+	}
+	
+	/**
+	 * MemberFunctionLookup
+	 * @param name
+	 * @param parameters
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 * 
+	 * Member lookup really proceeds as an unqualified lookup, but doesn't
+	 * include argument dependant scopes
+	 */
+	public Declaration MemberFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+		LookupData data = new LookupData( name, Declaration.t_function );
+		data.parameters = parameters;
+			
+		return Lookup( data, (Declaration) _contextStack.peek() );
+	}
+	
+	/**
+	 * UnqualifiedFunctionLookup
+	 * @param name
+	 * @param parameters
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 * 
+	 * 3.4.2-1 When an unqualified name is used as the post-fix expression in a
+	 * function call, other namespaces not consdiered during the usual
+	 * unqualified lookup may be searched.
+	 * 
+	 * 3.4.2-2 For each argument type T in the function call, there is a set of
+	 * zero or more associated namespaces and a set of zero or more associated
+	 * classes to be considered.
+	 * 
+	 * If the ordinary unqualified lookup of the name find the declaration of a
+	 * class member function, the associated namespaces and classes are not
+	 * considered.  Otherwise, the set of declarations found by the lookup of
+	 * the function name is the union of the set of declarations found using
+	 * ordinary unqualified lookup and the set of declarations found in the
+	 * namespaces and classes associated with the argument types.
+	 */
+	public Declaration UnqualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+		//figure out the set of associated scopes first, so we can remove those that are searched
+		//during the normal lookup to avoid doing them twice
+		HashSet associated = new HashSet();
+		//collect associated namespaces & classes.
+		int size = parameters.size();
+		Iterator iter = parameters.iterator();
+		Declaration.ParameterInfo param = null;
+		for( int i = size; i > 0; i-- ){
+			param = (Declaration.ParameterInfo) iter.next();
+			
+			getAssociatedScopes( param.typeDeclaration, associated );
+			//if T is a pointer to a data member of class X, its associated namespaces and classes
+			//are those associated with the member type together with those associated with X
+			if( param.ptrOperator != null && 
+			   (param.ptrOperator.equals("*") || param.ptrOperator.equals("[]")) &&
+			 	param.typeDeclaration._containingScope.isType( Declaration.t_class, Declaration.t_union ) )
+			{
+				getAssociatedScopes( param.typeDeclaration._containingScope, associated );
+			}
+		}
+		
+		LookupData data = new LookupData( name, Declaration.t_function );
+		data.parameters = parameters;
+		data.associated = associated;
+		
+		Declaration found = Lookup( data, (Declaration) _contextStack.peek() );
+		
+		//if we haven't found anything, or what we found is not a class member, consider the 
+		//associated scopes
+		if( found == null || found._containingScope.getType() != Declaration.t_class ){
+			LinkedList foundList = new LinkedList();
+			
+			if( found != null ){
+				foundList.add( found );
+			}
+			
+			iter = associated.iterator();
+			
+			Declaration decl;
+			Declaration temp;
+			
+			//use while hasNext instead of forloop since the lookup might remove
+			//items from the collection.  
+			//Actually, I think that there will be no removals, but leave it like this anyway
+			while( iter.hasNext() ){
+				decl = (Declaration) iter.next();
+				
+				data.qualified = true;
+				data.ignoreUsingDirectives = true;
+				temp = Lookup( data, decl );
+				if( temp != null ){
+					foundList.add( temp );
+				}
+			}
+			
+			found = ResolveAmbiguities( data, foundList );
+		}
+		
+		return found;
+	}
+
+	/**
+	 * LookupForFriendship
+	 * @param name
+	 * @return Declaration
+	 * 7.3.1.2-3 When looking for a prior declaration of a class or a function
+	 * declared as a friend, scopes outside the innermost enclosing namespace
+	 * scope are not considered.
+	 * 11.4-9 If a friend declaration appears in a local class and the name
+	 * specified is an unqualified name, a prior declaration is looked up
+	 * without considering scopes that are outside the innermost enclosing non-
+	 * class scope.
+	 */
+	private Declaration LookupForFriendship( String name ) throws ParserSymbolTableException{
+		LookupData data = new LookupData( name, -1 );
+		
+		Declaration decl = (Declaration) _contextStack.peek();
+		boolean inClass = (decl.getType() == Declaration.t_class);
+		
+		Declaration enclosing = decl._containingScope;
+		while( enclosing != null && (inClass ? enclosing.getType() != Declaration.t_class
+											  :	enclosing.getType() == Declaration.t_namespace) )
+		{                                        		
+			enclosing = enclosing._containingScope;
+		}
+
+		data.stopAt = enclosing;
+		
+		return Lookup( data, (Declaration) _contextStack.peek() );
+	}
+		
+	public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException{
 		if( namespace.getType() != Declaration.t_namespace ){
-			throw new ParserSymbolTableException();
+			throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
 		}
 			
 		Declaration declaration = (Declaration) _contextStack.peek();
@@ -133,10 +316,77 @@
 		declaration._usingDirectives.add( namespace );
 	}
 	
+	/**
+	 * addUsingDeclaration
+	 * @param obj
+	 * @throws ParserSymbolTableException
+	 * 
+	 * 7.3.3-9  The entity declared by a using-declaration shall be known in the
+	 * context using it according to its definition at the point of the using-
+	 * declaration.  Definitions added to the namespace after the using-
+	 * declaration are not considered when a use of the name is made.
+	 * 
+	 * 7.3.3-4 A using-declaration used as a member-declaration shall refer to a
+	 * member of a base class of the class being defined, shall refer to a
+	 * member of an anonymous union that is a member of a base class of the
+	 * class being defined, or shall refer to an enumerator for an enumeration
+	 * type that is a member of a base class of the class being defined.
+	 */
+	public Declaration addUsingDeclaration( Declaration obj ) throws ParserSymbolTableException{
+		Declaration clone = null;
+		Declaration context = (Declaration) _contextStack.peek();
+		boolean okToAdd = false;
+		
+		//7.3.3-4
+		if( context.isType( Declaration.t_class, Declaration.t_union ) ){
+			//a member of a base class
+			if( obj.getContainingScope().getType() == context.getType() ){
+				okToAdd = hasBaseClass( context, obj.getContainingScope() );		
+			} 
+			//TBD : a member of an _anonymous_ union
+			else if ( obj.getContainingScope().getType() == Declaration.t_union ) {
+				Declaration union = obj.getContainingScope();
+				okToAdd = hasBaseClass( context, union.getContainingScope() ); 
+			}
+			//an enumerator for an enumeration
+			else if ( obj.getType() == Declaration.t_enumerator ){
+				Declaration enumeration = obj.getContainingScope();
+				okToAdd = hasBaseClass( context, enumeration.getContainingScope() );
+			}
+		} else {
+			okToAdd = true;
+		}
+		
+		if( okToAdd ){
+			clone = (Declaration) obj.clone(); //7.3.3-9
+			addDeclaration( clone );
+		} else {
+			throw new ParserSymbolTableException();
+		}
+		return clone;
+	}
+	
 	public void addDeclaration( Declaration obj ) throws ParserSymbolTableException{
+		
 		Declaration containing = (Declaration) _contextStack.peek();
+			
+		//handle enumerators
+		if( obj.getType() == Declaration.t_enumerator ){
+			//a using declaration of an enumerator will not be contained in a
+			//enumeration.
+			if( containing.getType() == Declaration.t_enumeration ){
+				//Following the closing brace of an enum-specifier, each enumerator has the type of its 
+				//enumeration
+				obj.setTypeDeclaration( containing );
+				//Each enumerator is declared in the scope that immediately contains the enum-specifier	
+				containing = containing.getContainingScope();
+			}
+		}
+		
 		Map declarations = containing.getContainedDeclarations();
 		
+		boolean unnamed = obj.getName().equals( "" );
+		
 		Object origObj = null;
 		
 		obj.setContainingScope( containing );
@@ -161,7 +411,7 @@
 				throw new ParserSymbolTableException();
 			}
 			
-			if( (origList == null) ? isValidOverload( origDecl, obj ) : isValidOverload( origList, obj ) ){
+			if( unnamed || (origList == null) ? isValidOverload( origDecl, obj ) : isValidOverload( origList, obj ) ){
 				if( origList == null ){
 					origList = new LinkedList();
 					origList.add( origDecl );
@@ -174,11 +424,84 @@
 					//origList is already in _containedDeclarations
 				}
 			} else {
-				throw new ParserSymbolTableException();
+				throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidOverload );
 			}
 		} else {
 			declarations.put( obj.getName(), obj );
 		}
+		
+		//take care of the this pointer
+		if( obj.getType() == Declaration.t_function && !obj.isStatic() ){
+			addThis( obj );
+		}
+	}
+	
+	/**
+	 * 
+	 * @param name
+	 * @return Declaration
+	 * @throws ParserSymbolTableException
+	 * 
+	 * 7.3.1.2-3 If a friend declaration in a non-local class first declares a
+	 * class or function, the friend class or function is a member of the
+	 * innermost enclosing namespace.
+	 * 
+	 * TBD: if/when the parser symbol table starts caring about visibility
+	 * (public/protected/private) we will need to do more to record friendship.
+	 */
+	public Declaration addFriend( String name ) throws ParserSymbolTableException{
+		Declaration friend = LookupForFriendship( name  );
+		
+		if( friend == null ){
+			friend = new Declaration( name );
+			friend.setNeedsDefinition( true );
+			
+			Declaration decl = (Declaration) _contextStack.peek();
+			Declaration containing = decl._containingScope;
+			//find innermost enclosing namespace
+			while( containing != null && containing.getType() != Declaration.t_namespace ){
+				containing = containing._containingScope;
+			}
+			
+			Declaration namespace = (containing == null ) ? _compilationUnit : containing; 
+			push( namespace );
+			addDeclaration( friend );
+			pop(); 
+		}
+			
+		return friend;
+	}
+	
+	/**
+	 * 
+	 * @param obj
+	 * @throws ParserSymbolTableException
+	 * 9.3.2-1 In the body of a nonstatic member function... the type of this of
+	 * a class X is X*.  If the member function is declared const, the type of
+	 * this is const X*, if the member function is declared volatile, the type
+	 * of this is volatile X*....
+	 */
+	private void addThis( Declaration obj ) throws ParserSymbolTableException{
+		if( obj.getType() != Declaration.t_function || obj.isStatic() ){
+			return;
+		}
+		
+		if( obj._containingScope.isType( Declaration.t_class, Declaration.t_union ) ){
+			//check to see if there is already a this object, since using declarations
+			//of function will have them from the original declaration
+			LookupData data = new LookupData( "this", -1 );
+			if( LookupInContained( data, obj ) == null ){
+				Declaration thisObj = new Declaration("this");
+				thisObj.setType( Declaration.t_type );
+				thisObj.setTypeDeclaration( obj._containingScope );
+				thisObj.setCVQualifier( obj.getCVQualifier() );
+				thisObj.setPtrOperator("*");
+				
+				push( obj );
+				addDeclaration( thisObj );
+				pop();
+			}
+		}		
 	}
 	
 	/**
@@ -206,43 +529,45 @@
 			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( !data.ignoreUsingDirectives ){
+			//check nominated namespaces
+			//the transitives list is populated in LookupInNominated, and then 
+			//processed in ProcessDirectives
 			
-		//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 );
+			data.visited.clear(); //each namesapce is searched at most once, so keep track
 			
-			if( inDeclaration._usingDirectives != null ){
-				ProcessDirectives( inDeclaration, data, inDeclaration._usingDirectives );
+			tempList = LookupInNominated( data, inDeclaration, transitives );
+					
+			if( tempList != null ){
+				foundNames.addAll( tempList );
 			}
-						
-			while( data.usingDirectives != null && data.usingDirectives.get( inDeclaration ) != null ){
-				transitives.clear();
 				
-				tempList = LookupInNominated( data, inDeclaration, transitives );
+			//if we are doing a qualified lookup, only process using directives if
+			//we haven't found the name yet (and if we aren't ignoring them). 
+			if( !data.qualified || foundNames.size() == 0 ){
+				ProcessDirectives( inDeclaration, data, transitives );
 				
-				if( tempList != null ){
-					foundNames.addAll( tempList );
+				if( inDeclaration._usingDirectives != null ){
+					ProcessDirectives( inDeclaration, data, inDeclaration._usingDirectives );
 				}
-
-				if( !data.qualified || foundNames.size() == 0 ){
-					ProcessDirectives( inDeclaration, data, transitives );
+							
+				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 );
+		decl = ResolveAmbiguities( data, foundNames );
 		if( decl != null ){
 			return decl;
 		}
@@ -343,6 +668,11 @@
 		Declaration temp  = null;
 		Object obj = null;
 	
+		if( data.associated != null ){
+			//we are looking in lookIn, remove it from the associated scopes list
+			data.associated.remove( lookIn );
+		}
+		
 		Map declarations = lookIn.getContainedDeclarations();
 		if( declarations == null )
 			return null;
@@ -353,7 +683,7 @@
 			//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 ){	
@@ -381,7 +711,7 @@
 		if( found == null || found.size() == 0 )			
 			return null;
 		
-		return ResolveAmbiguities( found );
+		return ResolveAmbiguities( data, found );
 	}
 	
 	/**
@@ -393,14 +723,21 @@
 	 */
 	private static Declaration LookupInParents( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
 		LinkedList scopes = lookIn.getParentScopes();
-		Declaration decl = null;
 		Declaration temp = null;
+		Declaration decl = null;
+		
 		Iterator iterator = null;
 		Declaration.ParentWrapper wrapper = null;
 		
 		if( scopes == null )
 			return null;
 				
+		//use data to detect circular inheritance
+		if( data.inheritanceChain == null )
+			data.inheritanceChain = new HashSet();
+		
+		data.inheritanceChain.add( lookIn );
+		
 		iterator = scopes.iterator();
 			
 		int size = scopes.size();
@@ -413,15 +750,27 @@
 					data.visited.add( wrapper.parent );
 				}
 				
-				//is this name define in this scope?
-				temp =  LookupInContained( data, wrapper.parent );
+				//HashSet.add returns false if wrapper.parent is already in the set
+				//this means we have circular inheritance
+				if( data.inheritanceChain.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 = LookupInParents( data, wrapper.parent );
+					}
+					
+					data.inheritanceChain.remove( wrapper.parent );
+					
+				} else {
+					throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance );
 				}
+				
 			}	
 			
 			if( temp != null && temp.isType( data.type ) ){
+
 				if( decl == null  ){
 					decl = temp;
 				} else if ( temp != null ) {
@@ -458,18 +807,14 @@
 		int origType = origDecl.getType();
 		int newType  = newDecl.getType();
 		
-		if( (origType >= Declaration.t_class && origType <= Declaration.t_enum) && //class name or enumeration ...
+		if( (origType >= Declaration.t_class && origType <= Declaration.t_enumeration) && //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;
+		return isValidFunctionOverload( origDecl, newDecl );
 	}
 	
 	private static boolean isValidOverload( LinkedList origList, Declaration newDecl ){
@@ -486,12 +831,12 @@
 			
 			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 );
+			boolean valid = (( decl.getType() >= Declaration.t_class && decl.getType() <= Declaration.t_enumeration ) ||
+							  isValidFunctionOverload( decl, newDecl ));
 			
 			while( valid && iter.hasNext() ){
 				decl = (Declaration) iter.next();
-				valid = ( decl.getType() == Declaration.t_function );
+				valid = isValidFunctionOverload( decl, newDecl );
 			}
 			
 			return valid;
@@ -501,7 +846,31 @@
 		return true;
 	}
 	
-	static private Declaration ResolveAmbiguities( LinkedList items ) throws ParserSymbolTableException{
+	private static boolean isValidFunctionOverload( Declaration origDecl, Declaration newDecl ){
+		if( origDecl.getType() != Declaration.t_function || newDecl.getType() != Declaration.t_function ){
+			return false;
+		}
+		
+		if( origDecl.hasSameParameters( newDecl ) ){
+			//functions with the same name and same parameter types cannot be overloaded if any of them
+			//is static
+			if( origDecl.isStatic() || newDecl.isStatic() ){
+				return false;
+			}
+			
+			//if none of them are static, then the function can be overloaded if they differ in the type
+			//of their implicit object parameter.
+			if( origDecl.getCVQualifier() != newDecl.getCVQualifier() ){
+				return true;
+			}
+			
+			return false;
+		}
+		
+		return true;
+	}
+	
+	static private Declaration ResolveAmbiguities( LookupData data, LinkedList items ) throws ParserSymbolTableException{
 		Declaration decl = null;
 	
 		int size = items.size(); 
@@ -514,8 +883,8 @@
 			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 );
+			if( first.getType() >= Declaration.t_class && first.getType() <= Declaration.t_enumeration ){
+				return ResolveAmbiguities( data, items );
 			}
 		
 			//else, if the first is an object (ie not a function), the rest must be the same
@@ -529,11 +898,11 @@
 			
 				if( needSame ){
 					if( decl != first ){
-						throw new ParserSymbolTableException();
+						throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
 					}
 				} else {
 					if( decl.getType() != Declaration.t_function ){
-						throw new ParserSymbolTableException();
+						throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
 					}
 				}
 			}
@@ -542,16 +911,63 @@
 				return first;
 			} else {
 				items.addFirst( first );
-				return ResolveFunction( items );
+				return ResolveFunction( data, items );
 			}
 		}
 	}
 
-	static private Declaration ResolveFunction( LinkedList functions ){
-		//TBD
+	static private Declaration ResolveFunction( LookupData data, LinkedList functions ){
+		
+		int numParameters = ( data.parameters == null ) ? 0 : data.parameters.size();
+		int num;	
+			
+		//Trim the list down to the set of viable functions
+		Declaration function;
+		Iterator iter = functions.iterator();
+		while( iter.hasNext() ){
+			function = (Declaration) iter.next();
+			num = ( function._parameters == null ) ? 0 : function._parameters.size();
+		
+			//if there are m arguments in the list, all candidate functions having m parameters
+			//are viable	 
+			if( num == numParameters ){
+			 	continue;
+			} 
+			//A candidate function having fewer than m parameters is viable only if it has an 
+			//ellipsis in its parameter list.
+			else if( num < numParameters ) {
+				//TBD ellipsis
+				//not enough parameters, remove it
+				iter.remove();		
+			} 
+			//a candidate function having more than m parameters is viable only if the (m+1)-st
+			//parameter has a default argument
+			else {
+				 ListIterator listIter = function._parameters.listIterator( num - 1 );
+				 Declaration.ParameterInfo param;
+				 for( int i = num; i > ( numParameters - num ); i-- ){
+				 	param = (Declaration.ParameterInfo)listIter.previous();
+				 	if( !param.hasDefaultValue ){
+				 		iter.remove();
+				 		break;
+					}
+				}
+			}
+		}
+		
+		//TBD, rank implicit conversion sequences to determine which one is best.
+		int size = functions.size();
+		if( size == 0 ){
+			return null;
+		}
+		else if( size == 1) {
+			return (Declaration) functions.getFirst();
+		}
+		
 		return null;
 	}
 	
+
 	/**
 	 * function ProcessDirectives
 	 * @param Declaration decl
@@ -624,18 +1040,99 @@
 		}
 	}
 	
+	/**
+	 * 
+	 * @param obj
+	 * @param base
+	 * @return boolean
+	 * figure out if base is a base class of obj.
+	 * 
+	 * TBD: Consider rewriting iteratively for performance.
+	 */
+	static private boolean hasBaseClass( Declaration obj, Declaration base ){
+		boolean isABaseClass = false;
+		
+		if( obj._parentScopes != null ){	
+			Declaration decl;
+			Declaration.ParentWrapper wrapper;
+			
+			Iterator iter = obj._parentScopes.iterator();
+			int size = obj._parentScopes.size();
+			
+			for( int i = size; i > 0; i-- ){
+				wrapper = (Declaration.ParentWrapper) iter.next();	
+				decl = wrapper.parent;
+				
+				if( decl == base || hasBaseClass( decl, base ) ){
+					return true;
+				}
+			}
+		}
+		
+		return false;
+	}
+
+	static private void getAssociatedScopes( Declaration decl, HashSet associated ){
+		if( decl == null ){
+			return;
+		}
+		//if T is a class type, its associated classes are the class itself,
+		//and its direct and indirect base classes. its associated Namespaces are the 
+		//namespaces in which its associated classes are defined	
+		if( decl.getType() == Declaration.t_class ){
+			associated.add( decl );
+			getBaseClassesAndContainingNamespaces( decl, associated );
+		} 
+		//if T is a union or enumeration type, its associated namespace is the namespace in 
+		//which it is defined. if it is a class member, its associated class is the member's
+		//class
+		else if( decl.getType() == Declaration.t_union || decl.getType() == Declaration.t_enumeration ){
+			associated.add( decl._containingScope );
+		}
+	}
+	
+	static private void getBaseClassesAndContainingNamespaces( Declaration obj, HashSet classes ){
+		if( obj._parentScopes != null ){
+			if( classes == null ){
+				return;
+			}
+			
+			Iterator iter = obj._parentScopes.iterator();
+			int size = obj._parentScopes.size();
+			Declaration base;
+			
+			for( int i = size; i > 0; i-- ){
+				base = (Declaration) iter.next();	
+				classes.add( base );
+				if( base._containingScope.getType() == Declaration.t_namespace ){
+					classes.add( base._containingScope );
+				}
+				
+				getBaseClassesAndContainingNamespaces( base, classes );
+			}
+		}
+	}
+	
 	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 HashSet inheritanceChain;		//used to detect circular inheritance
+		
+		public LinkedList parameters;			//parameter info for resolving functions
+		public HashSet associated;				//associated namespaces for argument dependant lookup
+		public Declaration stopAt;				//stop looking along the stack once we hit this declaration
+				 
 		public int type = -1;
 		public int upperType = 0;
 		public boolean qualified = false;
+		public boolean ignoreUsingDirectives = false;
 
 		public LookupData( String n, int t ){
 			name = n;
Index: 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.3
diff -u -r1.3 ParserSymbolTableException.java
--- org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java	6 Mar 2003 18:42:26 -0000	1.3
+++ org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java	20 Mar 2003 22:22:13 -0000
@@ -36,9 +36,11 @@
 		reason = r;
 	}
 
-	public static final int r_Unspecified   = -1;
-	public static final int r_AmbiguousName =  0;
-	public static final int r_BadTypeInfo   =  1;
+	public static final int r_Unspecified   			= -1;
+	public static final int r_AmbiguousName 			=  0;
+	public static final int r_BadTypeInfo   			=  1;
+	public static final int r_CircularInheritance	=  2;
+	public static final int r_InvalidOverload		=  3;
 	
 	public int reason = -1;
 }
Index: 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.5
diff -u -r1.5 ParserSymbolTableTest.java
--- org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	12 Mar 2003 15:35:35 -0000	1.5
+++ org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	20 Mar 2003 22:20:04 -0000
@@ -12,6 +12,7 @@
 package org.eclipse.cdt.core.parser.tests;
 
 import java.util.Iterator;
+import java.util.LinkedList;
 import java.util.Map;
 
 import junit.framework.TestCase;
@@ -244,6 +245,33 @@
 	}	
 	
 	/**
+	 * 
+	 * @throws Exception
+	 * test for circular inheritance 
+	 */
+	public void testCircularParentLookup() throws Exception{
+		newTable();
+		
+		Declaration a = new Declaration("a");
+		table.addDeclaration( a );
+		
+		Declaration b = new Declaration("b");
+		table.addDeclaration(b);
+		
+		a.addParent( b );
+		b.addParent( a );
+		
+		table.push( a );
+		 
+		try{
+			Declaration look = table.Lookup("foo");
+			assertTrue( false );
+		} catch ( ParserSymbolTableException e) {
+			assertEquals( e.reason, ParserSymbolTableException.r_CircularInheritance );
+		}
+		
+	}
+	/**
 	 * testVirtualParentLookup
 	 * 
 	 * @throws Exception
@@ -320,7 +348,7 @@
 			assertTrue( false );
 		}
 		catch( ParserSymbolTableException e){
-			assertTrue( true );
+			assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
 		}
 	}
 	
@@ -351,7 +379,10 @@
 		table.addDeclaration( d );
 		
 		Declaration enum = new Declaration("enum");
-		enum.setType( Declaration.t_enumerator );
+		enum.setType( Declaration.t_enumeration );
+		
+		Declaration enumerator = new Declaration( "enumerator" );
+		enumerator.setType( Declaration.t_enumerator );
 		
 		Declaration stat = new Declaration("static");
 		stat.setStatic(true);
@@ -360,6 +391,9 @@
 		
 		table.push(d);
 		table.addDeclaration( enum );
+		table.push( enum );
+		table.addDeclaration( enumerator );
+		table.pop();
 		table.addDeclaration( stat );
 		table.addDeclaration( x );
 		table.pop();
@@ -371,7 +405,7 @@
 		
 		table.push( a );
 		try{
-			table.Lookup( "enum" );
+			table.Lookup( "enumerator" );
 			assertTrue( true );	
 		}
 		catch ( ParserSymbolTableException e){
@@ -391,7 +425,7 @@
 			assertTrue( false );	
 		}
 		catch ( ParserSymbolTableException e){
-			assertTrue( true );
+			assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
 		}
 	}
 	
@@ -477,46 +511,6 @@
 	}
 	
 	/**
-	 * testFunctions
-	 * @throws Exception
-	 * Functions are stored by signature. Where the signature can really be of
-	 * any for you like, as long as it can't possibly be a regular name (ie
-	 * including the parenthese is good...)
-	 * So lookup of function names proceeds inthe same manner as normal names,
-	 * this test doesn't really test anything new
-	 */
-	
-	public void testFunctions() throws Exception{
-		newTable();
-		
-		Declaration cls = new Declaration( "class");
-		Declaration f1 = new Declaration("foo()");
-		Declaration f2 = new Declaration("foo(int)");
-		Declaration f3 = new Declaration("foo(int,char)");
-		
-		table.addDeclaration(cls);
-		table.push(cls);
-		
-		table.addDeclaration( f1 );
-		table.addDeclaration( f2 );
-		table.addDeclaration( f3 );
-		
-		//return type can be specified by setting the TypeDeclaration
-		Declaration returnType = new Declaration("return");
-		f1.setTypeDeclaration( returnType );
-		f2.setTypeDeclaration( returnType );
-		f3.setTypeDeclaration( returnType );
-		
-		assertEquals( table.Lookup("foo()"), f1 );
-		assertEquals( table.Lookup("foo(int)"), f2 );
-		assertEquals( table.Lookup("foo(int,char)"), f3 );
-		
-		//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
 	 * 
@@ -649,7 +643,8 @@
 		}
 		catch ( ParserSymbolTableException e )
 		{
-			assertTrue(true); //ambiguous B::C::i and A::i
+			//ambiguous B::C::i and A::i
+			assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
 		}
 		table.pop(); //end f2
 		table.pop(); //end nsD
@@ -732,7 +727,8 @@
 		}
 		catch ( ParserSymbolTableException e )
 		{
-			assertTrue( true );		//ambiguous, both M::i and N::i are visible.
+			//ambiguous, both M::i and N::i are visible.
+			assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
 		}
 		
 		look = table.LookupNestedNameSpecifier("N");
@@ -1025,9 +1021,551 @@
 		try{
 			look = table.QualifiedLookup( "y" );
 			assertTrue(false);
-		} catch ( Exception e ) {
-			assertTrue(true);
+		} catch ( ParserSymbolTableException e ) {
+			assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
 		}
 	}
 	
+	/**
+	 * In a definition for a namespace member in which the declarator-id is a
+	 * qualified-id, given that the qualified-id for the namespace member has
+	 * the form "nested-name-specifier unqualified-id", the unqualified-id shall
+	 * name a member of the namespace designated by the nested-name-specifier.
+	 * 
+	 * namespace A{    
+	 *    namespace B{       
+	 *       void  f1(int);    
+	 *    }  
+	 *    using  namespace B; 
+	 * }
+	 * void A::f1(int) { ... } //ill-formed, f1 is not a member of A
+	 */
+	public void testLookupMemberForDefinition() throws Exception{
+		newTable();
+	
+		Declaration nsA = new Declaration( "A" );
+		nsA.setType( Declaration.t_namespace );
+		table.addDeclaration( nsA );
+		table.push( nsA );
+	
+		Declaration nsB = new Declaration( "B" );
+		nsB.setType( Declaration.t_namespace );
+		table.addDeclaration( nsB );
+		table.push( nsB );
+	
+		Declaration f1 = new Declaration("f1");
+		f1.setType( Declaration.t_function );
+		table.addDeclaration( f1 );
+	
+		table.pop();
+	
+		table.addUsingDirective( nsB );
+		table.pop();
+	
+		Declaration look = table.LookupNestedNameSpecifier( "A" );
+		assertEquals( nsA, look );
+		table.push( look );
+	
+		look = table.LookupMemberForDefinition( "f1" );
+		assertEquals( look, null );
+	
+		//but notice if you wanted to do A::f1 as a function call, it is ok
+		look = table.QualifiedLookup( "f1" );
+		assertEquals( look, f1 );
+	}
+	
+	/**
+	 * testUsingDeclaration
+	 * @throws Exception
+	 * 7.3.3-4 A using-declaration used as a member-declaration shall refer to a
+	 * member of a base-class of the class being defined, shall refer to a
+	 * member of an anonymous union that is a member of a base class of the
+	 * class being defined or shall refer to an enumerator for an enumeration
+	 * type that is a member of a base class of the class being defined
+	 *
+	 * struct B {
+	 *    void f( char );
+	 *    enum E { e };
+	 *    union { int x; };
+	 * };
+	 * class C {
+	 *	  int g();
+	 * }
+	 * struct D : B {
+	 *    using B::f;	//ok, B is a base class of D
+	 *    using B::e;   //ok, e is an enumerator in base class B
+	 *    using B::x;   //ok, x is an union member of base class B
+	 *    using C::g;   //error, C isn't a base class of D
+	 * }
+	 */
+	public void testUsingDeclaration() throws Exception{
+		newTable();
+		
+		Declaration B = new Declaration("B");
+		B.setType( Declaration.t_struct );
+		table.addDeclaration( B );
+		table.push( B );
+		
+		Declaration f = new Declaration("f");
+		f.setType( Declaration.t_function );
+		table.addDeclaration( f );
+	
+		Declaration E = new Declaration( "E" );
+		E.setType( Declaration.t_enumeration );
+		table.addDeclaration( E );
+		
+		table.push( E );
+		Declaration e = new Declaration( "e" );
+		e.setType( Declaration.t_enumerator );
+		table.addDeclaration( e );
+		table.pop();
+		
+		//TBD: Anonymous unions are not yet implemented
+		
+		table.pop();
+		
+		Declaration C = new Declaration( "C" );
+		C.setType( Declaration.t_class );
+		table.addDeclaration( C );
+		
+		table.push( C );
+		Declaration g = new Declaration( "g" );
+		g.setType( Declaration.t_function );
+		table.addDeclaration( g );
+		table.pop();
+		
+		Declaration D = new Declaration( "D" );
+		D.setType( Declaration.t_struct );
+		Declaration look = table.Lookup( "B" );
+		assertEquals( look, B );
+		D.addParent( look );
+		
+		table.addDeclaration( D );
+		table.push( D );
+		
+		Declaration lookB = table.LookupNestedNameSpecifier("B");
+		assertEquals( lookB, B );
+		table.push( lookB );
+		look = table.QualifiedLookup( "f" );
+		table.pop();
+		
+		assertEquals( look, f );
+		table.addUsingDeclaration( look );
+		
+		table.push( lookB );
+		look = table.QualifiedLookup( "e" );
+		table.pop();
+		assertEquals( look, e );
+		table.addUsingDeclaration( look );
+		  
+		//TBD anonymous union
+		//table.push( lookB );
+		//look = table.QualifiedLookup( "x")
+		//table.pop();
+		//table.addUsingDeclaration( look );
+		
+		look = table.LookupNestedNameSpecifier("C");
+		assertEquals( look, C );
+		table.push( look );
+		look = table.QualifiedLookup("g");
+		table.pop();
+		assertEquals( look, g );
+		
+		try{
+			table.addUsingDeclaration( look );
+			assertTrue( false );
+		}
+		catch ( ParserSymbolTableException exception ){
+			assertTrue( true );
+		}
+	}
+	
+	/**
+	 * testUsingDeclaration_2
+	 * @throws Exception
+	 * 7.3.3-9 The entity declared by a using-declaration shall be known in the
+	 * context using it according to its definition at the point of the using-
+	 * declaration.  Definitions added to the namespace after the using-
+	 * declaration are not considered when a use of the name is made.
+	 * 
+	 * namespace A {
+	 *     void f(int);
+	 * }
+	 * using A::f;
+	 * 
+	 * namespace A {
+	 * 	   void f(char);
+	 * }
+	 * void foo(){
+	 * 	  f('a');    //calls f( int )
+	 * }
+	 * void bar(){
+	 * 	  using A::f;
+	 * 	  f('a');    //calls f( char );
+	 * }	
+	 *
+	 * TBD: we need to support using declarations for overloaded functions.
+	 * TBD: function overload resolution is not done yet, so the call to f in
+	 * bar() can't be tested yet.
+	 */
+	public void testUsingDeclaration_2() throws Exception{
+		newTable();
+		
+		Declaration A = new Declaration( "A" );
+		A.setType( Declaration.t_namespace );
+		table.addDeclaration( A );
+		
+		table.push( A );
+		
+		Declaration f1 = new Declaration( "f" );
+		f1.setType( Declaration.t_function );
+		f1.setReturnType( Declaration.t_void );
+		f1.addParameter( Declaration.t_int, "", false );
+		table.addDeclaration( f1 );
+		
+		table.pop();
+		
+		Declaration look = table.LookupNestedNameSpecifier("A");
+		assertEquals( look, A );
+		table.push( A );
+		look = table.QualifiedLookup("f");
+		assertEquals( look, f1 );
+		table.pop();
+		
+		Declaration usingF = table.addUsingDeclaration( look );
+		
+		look = table.Lookup("A");
+		assertEquals( look, A );
+		
+		table.push( look );
+		Declaration f2 = new Declaration("f");
+		f2.setType( Declaration.t_function );
+		f2.setReturnType( Declaration.t_void );
+		f2.addParameter( Declaration.t_char, "", false );
+		
+		table.addDeclaration( f2 );
+		
+		table.pop();
+		
+		Declaration foo = new Declaration("foo");
+		foo.setType( Declaration.t_function );
+		table.addDeclaration( foo );
+		table.push( foo );
+		LinkedList paramList = new LinkedList();
+		Declaration.ParameterInfo param = foo.new ParameterInfo();
+		param.typeInfo = Declaration.t_char;
+		paramList.add( param );
+		
+		look = table.UnqualifiedFunctionLookup( "f", paramList );
+		assertEquals( look, usingF );
+		
+	}
+	
+	/**
+	 * testThisPointer
+	 * @throws Exception
+	 * In the body of a nonstatic member function... the type of this of a class
+	 * X is X*.  If the member function is declared const, the type of this is
+	 * const X*, if the member function is declared volatile, the type of this
+	 * is volatile X*....
+	 */
+	public void testThisPointer() throws Exception{
+		newTable();
+		
+		Declaration cls = new Declaration("class");
+		cls.setType( Declaration.t_class );
+		
+		Declaration fn = new Declaration("function");
+		fn.setType( Declaration.t_function );
+		fn.setCVQualifier("const");
+		
+		table.addDeclaration( cls );
+		table.push( cls );
+		
+		table.addDeclaration( fn );
+		table.push( fn );
+		
+		Declaration look = table.Lookup("this");
+		assertTrue( look != null );
+		
+		assertEquals( look.getType(), Declaration.t_type );
+		assertEquals( look.getTypeDeclaration(), cls );
+		assertEquals( look.getPtrOperator(), "*" );
+		assertEquals( look.getCVQualifier(), fn.getCVQualifier() );
+		assertEquals( look.getContainingScope(), fn );
+	}
+	
+	/**
+	 * testEnumerator
+	 * @throws Exception
+	 * Following the closing brace of an enum-specifier, each enumerator has the
+	 * type of its enumeration.
+	 * The enum-name and each enumerator declared by an enum-specifier is
+	 * declared in the scope that immediately contains the enum-specifier
+	 */
+	public void testEnumerator() throws Exception{
+		newTable();
+		
+		Declaration cls = new Declaration("class");
+		cls.setType( Declaration.t_class );
+		
+		Declaration enumeration = new Declaration("enumeration");
+		enumeration.setType( Declaration.t_enumeration );
+		
+		table.addDeclaration( cls );
+		table.push( cls );
+		table.addDeclaration( enumeration );
+		table.push( enumeration );
+		
+		Declaration enumerator = new Declaration( "enumerator" );
+		enumerator.setType( Declaration.t_enumerator );
+		table.addDeclaration( enumerator );
+		
+		table.pop();
+		
+		Declaration look = table.Lookup( "enumerator" );
+		assertEquals( look, enumerator );
+		assertEquals( look.getContainingScope(), cls );
+		assertEquals( look.getTypeDeclaration(), enumeration );
+	}
+
+	/**
+	 * 
+	 * @throws Exception
+	 * 
+	 * namespace NS{
+	 *    class T {};
+	 *    void f( T );
+	 * }
+	 * NS::T parm;
+	 * int main(){
+	 *    f( parm );   //ok, calls NS::f
+	 * }
+	 */
+	public void testArgumentDependentLookup() throws Exception{
+		newTable();
+		
+		Declaration NS = new Declaration("NS");
+		NS.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( NS );
+		table.push( NS );
+		
+		Declaration T = new Declaration("T");
+		T.setType( Declaration.t_class );
+		
+		table.addDeclaration( T );
+		
+		Declaration f = new Declaration("f");
+		f.setType( Declaration.t_function );
+		f.setReturnType( Declaration.t_void );
+		
+		Declaration look = table.Lookup( "T" );
+		assertEquals( look, T );				
+		f.addParameter( look, "", false );
+		
+		table.addDeclaration( f );	
+		
+		table.pop(); //done NS
+				
+		look = table.LookupNestedNameSpecifier( "NS" );
+		assertEquals( look, NS );
+		table.push( look );
+		look = table.QualifiedLookup( "T" );
+		assertEquals( look, T );
+		table.pop();
+		
+		Declaration param = new Declaration("parm");
+		param.setType( Declaration.t_type );
+		param.setTypeDeclaration( look );
+		table.addDeclaration( param );
+		
+		Declaration main = new Declaration("main");
+		main.setType( Declaration.t_function );
+		main.setReturnType( Declaration.t_int );
+		table.addDeclaration( main );
+		table.push( main );
+		
+		LinkedList paramList = new LinkedList();
+		look = table.Lookup( "parm" );
+		assertEquals( look, param );
+		
+		Declaration.ParameterInfo p = look.new ParameterInfo();
+		p.typeInfo = look.getType();
+		p.typeDeclaration = look.getTypeDeclaration();
+		
+		paramList.add( p );
+		
+		look = table.UnqualifiedFunctionLookup( "f", paramList );
+		assertEquals( look, f );
+	}
+	
+	/**
+	 * testArgumentDependentLookup_2
+	 * @throws Exception
+	 * in the following, NS2 is an associated namespace of class B which is an
+	 * associated namespace of class A, so we should find f in NS2, we should
+	 * not find f in NS1 because usings are ignored for associated scopes.
+	 * 
+	 *
+	 * namespace NS1{
+	 *    void f( void * ){}; 
+	 * } 
+	 * namespace NS2{
+	 *	  using namespace NS1;
+	 * 	  class B {};
+	 *	  void f( void * ){}; 
+	 * }
+	 * 
+	 * class A : public NS2::B {};
+	 *
+	 * A a;
+	 * f( &a );
+	 *    
+	 */
+	public void testArgumentDependentLookup_2() throws Exception{
+		newTable();
+		
+		Declaration NS1 = new Declaration( "NS1" );
+		NS1.setType( Declaration.t_namespace );
+		 
+		table.addDeclaration( NS1 );
+		table.push( NS1 );
+		
+		Declaration f1 = new Declaration( "f" );
+		f1.setType( Declaration.t_function );
+		f1.setReturnType( Declaration.t_void );
+		f1.addParameter( Declaration.t_void, "*", false );
+		table.addDeclaration( f1 );
+		table.pop();
+		
+		Declaration NS2 = new Declaration( "NS2" );
+		NS2.setType( Declaration.t_namespace );
+		
+		table.addDeclaration( NS2 );
+		table.push( NS2 );
+		
+		Declaration look = table.Lookup( "NS1" );
+		assertEquals( look, NS1 );
+		table.addUsingDirective( look );
+		
+		Declaration B = new Declaration( "B" );
+		B.setType( Declaration.t_class );
+		table.addDeclaration( B );
+		
+		Declaration f2 = new Declaration( "f" );
+		f2.setType( Declaration.t_function );
+		f2.setReturnType( Declaration.t_void );
+		f2.addParameter( Declaration.t_void, "*", false );
+		table.addDeclaration( f2 );
+		table.pop();
+		
+		Declaration A = new Declaration( "A" );
+		A.setType( Declaration.t_class );
+		look = table.LookupNestedNameSpecifier( "NS2" );
+		assertEquals( look, NS2 );
+		table.push( look );
+		look = table.QualifiedLookup( "B" );
+		assertEquals( look, B );
+		A.addParent( look );
+		
+		table.addDeclaration( A );
+		
+		look = table.Lookup( "A" );
+		assertEquals( look, A );
+		Declaration a = new Declaration( "a" );
+		a.setType( Declaration.t_type );
+		a.setTypeDeclaration( look );
+		table.addDeclaration( a );
+		
+		LinkedList paramList = new LinkedList();
+		look = table.Lookup( "a" );
+		assertEquals( look, a );
+		Declaration.ParameterInfo param = look.new ParameterInfo( look.getType(), look, "&", false );
+		paramList.add( param );
+		
+		look = table.UnqualifiedFunctionLookup( "f", paramList );
+		assertEquals( look, f2 );
+	}
+	
+	/**
+	 * testFunctionOverloading
+	 * @throws Exception
+	 * Note that this test has been contrived to not strain the resolution as
+	 * that aspect is not yet complete.
+	 * 
+	 * class C
+	 * {   
+	 *    void foo( int i );
+	 *    void foo( int i, char c );
+	 *    void foo( int i, char c, C * ptr ); 
+	 * }
+	 *
+	 * C * c = new C;
+	 * c->foo( 1 );
+	 * c->foo( 1, 'a' );
+	 * c->foo( 1, 'a', c );
+	 * 
+	 */
+	
+	public void testFunctionOverloading() throws Exception{
+		newTable();
+		
+		Declaration C = new Declaration( "C" );
+		
+		table.addDeclaration(C);
+		table.push(C);
+				
+		Declaration f1 = new Declaration("foo");
+		f1.setType( Declaration.t_function );
+		f1.setReturnType( Declaration.t_void );
+		f1.addParameter( Declaration.t_int, "", false );
+		table.addDeclaration( f1 );
+		
+		Declaration f2 = new Declaration("foo");
+		f2.setType( Declaration.t_function );
+		f2.setReturnType( Declaration.t_void );
+		f2.addParameter( Declaration.t_int, "", false );
+		f2.addParameter( Declaration.t_char, "", false );
+		table.addDeclaration( f2 );
+		
+		Declaration f3 = new Declaration("foo");
+		f3.setType( Declaration.t_function );
+		f3.setReturnType( Declaration.t_void );
+		f3.addParameter( Declaration.t_int, "", false );
+		f3.addParameter( Declaration.t_char, "", false );
+		f3.addParameter( C, "*", false );
+		table.addDeclaration( f3 );
+		table.pop();
+		
+		Declaration look = table.Lookup("C");
+		assertEquals( look, C );
+		
+		Declaration c = new Declaration("c");
+		c.setType( Declaration.t_class );
+		c.setTypeDeclaration( look );
+		table.addDeclaration( c );
+		
+		look = table.Lookup( "c" );
+		assertEquals( look, c );
+		assertEquals( look.getTypeDeclaration(), C );
+		table.push( look.getTypeDeclaration() );
+		
+		LinkedList paramList = new LinkedList();
+		Declaration.ParameterInfo p1 = c.new ParameterInfo(Declaration.t_int, null, "", false);
+		Declaration.ParameterInfo p2 = c.new ParameterInfo(Declaration.t_char, null, "", false);
+		Declaration.ParameterInfo p3 = c.new ParameterInfo(Declaration.t_class, C, "", false);
+		
+		paramList.add( p1 );
+		look = table.MemberFunctionLookup( "foo", paramList );
+		assertEquals( look, f1 );
+		
+		paramList.add( p2 );
+		look = table.MemberFunctionLookup( "foo", paramList );
+		assertEquals( look, f2 );
+				
+		paramList.add( p3 );
+		look = table.MemberFunctionLookup( "foo", paramList );
+		assertEquals( look, f3 );
+	}
 }

Back to the top