Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Bug43110 - Parser support needed for functions with ellipses

This patch modifies the symbol table (and a little bit in the parser) to 
address bug 43110, handling of functions with ellipses (var args)

Core:
        Added IParameterizedSymbol.setHasVariableArgs() & 
hasVariableArgs()
        Modified ParserSymbolTable.resolveFunction & reduceToViable
        Modified CompleteParseASTFactory.createMethod & createFunction

Tests:
        Added CompleteParseASTTest.testBug43110_XRef
        Added ParserSymbolTableTest.testBug43110_Ellipses
        Added ParserSymbolTableTest.testBug43110_EllipsesRanking
        Added ParserSymbolTableTest.testBug43110_EllipsesRanking_2

Tested on windows

-Andrew

Index: parser/ChangeLog-parser
===================================================================
retrieving revision 1.15
diff -u -r1.15 ChangeLog-parser
--- parser/ChangeLog-parser	8 Jan 2004 16:57:48 -0000	1.15
+++ parser/ChangeLog-parser	8 Jan 2004 22:56:00 -0000
@@ -1,4 +1,10 @@
 2004-01-08 Andrew Niefer
+	fixing bug 43110 - Parser support needed for functions with ellipses
+	Added IParameterizedSymbol.setHasVariableArgs() & hasVariableArgs()
+	Modified ParserSymbolTable.resolveFunction & reduceToViable
+	Modified CompleteParseASTFactory.createMethod & createFunction
+
+2004-01-08 Andrew Niefer
 	Fixing 48307 - PST: Friendship needs to be handled better
 	Added IDerivableContainerSymbol.lookupFunctionForFriendship.
 	Modified IASTFactory.createMethod to take an ITokenDuple for the method name.
Index: parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java
===================================================================
retrieving revision 1.63
diff -u -r1.63 CompleteParseASTFactory.java
--- parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java	8 Jan 2004 16:57:48 -0000	1.63
+++ parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java	8 Jan 2004 22:56:05 -0000
@@ -1654,6 +1654,8 @@
 		IParameterizedSymbol symbol = pst.newParameterizedSymbol( name.getLastToken().getImage(), TypeInfo.t_function );
 		setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol);
 		
+		symbol.setHasVariableArgs( hasVariableArguments );
+		
 		setParameter( symbol, returnType, false, references );
 		setParameters( symbol, references, parameters.iterator() );
 		 
@@ -1935,6 +1937,8 @@
 		IParameterizedSymbol symbol = pst.newParameterizedSymbol( nameDuple.toString(), TypeInfo.t_function );
 		setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol);
 		setMethodTypeInfoBits( symbol, isConst, isVolatile, isVirtual, isExplicit );
+		symbol.setHasVariableArgs( hasVariableArguments );
+		
 		if(references == null)
 			references = new ArrayList();
     	
Index: parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java
===================================================================
retrieving revision 1.5
diff -u -r1.5 IParameterizedSymbol.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java	20 Nov 2003 15:22:56 -0000	1.5
+++ parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java	8 Jan 2004 22:56:07 -0000
@@ -45,6 +45,9 @@
 	public void setReturnType( ISymbol type );
 	public ISymbol getReturnType();
 	
+	public void setHasVariableArgs( boolean var );
+	public boolean hasVariableArgs( );
+	
 	public boolean	hasSpecializations();
 	public void 	addSpecialization( IParameterizedSymbol spec );
 	public List 	getSpecializations();	
Index: parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java
===================================================================
retrieving revision 1.1
diff -u -r1.1 ParameterizedSymbol.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java	20 Nov 2003 15:22:56 -0000	1.1
+++ parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java	8 Jan 2004 22:56:07 -0000
@@ -240,6 +240,13 @@
 		return _specializations;
 	}
 
+	public void setHasVariableArgs( boolean var ){
+		_hasVarArgs = var;
+	}
+	
+	public boolean hasVariableArgs( ){
+		return _hasVarArgs;
+	}
 
 	static private class AddParameterCommand extends Command{
 		public AddParameterCommand( IParameterizedSymbol container, ISymbol parameter ){
@@ -279,4 +286,5 @@
 	private		LinkedList	_specializations;		//template specializations
 	private		LinkedList	_argumentList;			//template specialization arguments
 	private 	ISymbol		_returnType;
+	private 	boolean		_hasVarArgs = false;	//whether or not this function has variable arguments
 }
Index: parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java
===================================================================
retrieving revision 1.32
diff -u -r1.32 ParserSymbolTable.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java	7 Jan 2004 02:00:17 -0000	1.32
+++ parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java	8 Jan 2004 22:56:08 -0000
@@ -850,10 +850,10 @@
 						}
 					}
 				}
-				throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
-			}else{
-				throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
 			}
+			
+			if( data.parameters == null )
+				throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
 		}
 		
 		IParameterizedSymbol bestFn = null;				//the best function
@@ -866,7 +866,6 @@
 		Iterator targetParams = null;
 		
 		int numTargetParams = 0;
-		int numParams = 0;
 		int comparison;
 		Cost cost = null;
 		Cost temp = null;
@@ -880,6 +879,16 @@
 		boolean currHasAmbiguousParam = false;
 		boolean bestHasAmbiguousParam = false;
 
+		List parameters = null;
+		
+		if( numSourceParams == 0 ){
+			parameters = new LinkedList();
+			parameters.add( new TypeInfo( TypeInfo.t_void, 0, null ) );
+			numSourceParams = 1;
+		} else {
+			parameters = data.parameters;
+		}
+		
 		for( int i = numFns; i > 0; i-- ){
 			currFn = (IParameterizedSymbol) iterFns.next();
 			
@@ -892,15 +901,14 @@
 				}
 			}
 			
-			sourceParams = data.parameters.iterator();
+			sourceParams = parameters.iterator();
 			
 			List parameterList = null;
-			if( currFn.getParameterList().isEmpty() ){
+			if( currFn.getParameterList().isEmpty() && !currFn.hasVariableArgs() ){
 				//the only way we get here and have no parameters, is if we are looking
 				//for a function that takes void parameters ie f( void )
 				parameterList = new LinkedList();
 				parameterList.add( currFn.getSymbolTable().newSymbol( "", TypeInfo.t_void ) );
-				targetParams = parameterList.iterator();
 			} else {
 				parameterList = currFn.getParameterList();
 			}
@@ -908,24 +916,33 @@
 			targetParams = parameterList.iterator();
 			numTargetParams = parameterList.size();
 			
-			//we only need to look at the smaller number of parameters
-			//(a larger number in the Target means default parameters, a larger
-			//number in the source means ellipses.)
-			numParams = ( numTargetParams < numSourceParams ) ? numTargetParams : numSourceParams;
-			
 			if( currFnCost == null ){
-				currFnCost = new Cost [ numParams ];	
+				currFnCost = new Cost [ numSourceParams ];	
 			}
 			
 			comparison = 0;
+			boolean varArgs = false;
 			
-			for( int j = 0; j < numParams; j++ ){
+			for( int j = 0; j < numSourceParams; j++ ){
 				source = (TypeInfo) sourceParams.next();
-				target = ((ISymbol)targetParams.next()).getTypeInfo();
-				if( source.equals( target ) ){
+				
+				if( targetParams.hasNext() )
+					target = ((ISymbol)targetParams.next()).getTypeInfo();
+				else 
+					varArgs = true;
+				
+				if( varArgs ){
+					cost = new Cost( source, null );
+					cost.rank = Cost.ELLIPSIS_CONVERSION;
+				} else if ( target.getHasDefault() && source.isType( TypeInfo.t_void ) && !source.hasPtrOperators() ){
+					//source is just void, ie no parameter, if target had a default, then use that
+					cost = new Cost( source, target );
+					cost.rank = Cost.IDENTITY_RANK;
+				} else if( source.equals( target ) ){
 					cost = new Cost( source, target );
 					cost.rank = Cost.IDENTITY_RANK;	//exact match, no cost
 				} else {
+				
 					cost = checkStandardConversionSequence( source, target );
 					
 					//12.3-4 At most one user-defined conversion is implicitly applied to
@@ -947,7 +964,7 @@
 			//In order for this function to be better than the previous best, it must
 			//have at least one parameter match that is better that the corresponding
 			//match for the other function, and none that are worse.
-			for( int j = 0; j < numParams; j++ ){ 
+			for( int j = 0; j < numSourceParams; j++ ){ 
 				if( currFnCost[ j ].rank < 0 ){
 					hasWorse = true;
 					hasBetter = false;
@@ -1021,10 +1038,13 @@
 			
 			//A candidate function having fewer than m parameters is viable only if it has an 
 			//ellipsis in its parameter list.
-			if( num < numParameters ) {
-				//TODO ellipsis
-				//not enough parameters, remove it
-				iter.remove();		
+			if( num < numParameters ){
+				if( function.hasVariableArgs() ) {
+					continue;
+				} else {
+					//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
@@ -2287,8 +2307,8 @@
 	{
 		
 		public Cost( TypeInfo s, TypeInfo t ){
-			source = new TypeInfo( s );
-			target = new TypeInfo( t );
+			source = ( s != null ) ? new TypeInfo( s ) : new TypeInfo();
+			target = ( t != null ) ? new TypeInfo( t ) : new TypeInfo();
 		}
 		
 		public TypeInfo source;
Index: ChangeLog
===================================================================
retrieving revision 1.162
diff -u -r1.162 ChangeLog
--- ChangeLog	8 Jan 2004 16:57:54 -0000	1.162
+++ ChangeLog	8 Jan 2004 22:58:20 -0000
@@ -1,4 +1,10 @@
 2004-01-08 Andrew Niefer
+	Added CompleteParseASTTest.testBug43110_XRef
+	Added ParserSymbolTableTest.testBug43110_Ellipses
+	Added ParserSymbolTableTest.testBug43110_EllipsesRanking
+	Added ParserSymbolTableTest.testBug43110_EllipsesRanking_2
+
+2004-01-08 Andrew Niefer
 	Added CompleteParseASTTest::testBug48307_FriendFunction_1
 	Added CompleteParseASTTest::testBug48307_FriendFunction_2
 	
Index: parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java
===================================================================
retrieving revision 1.46
diff -u -r1.46 CompleteParseASTTest.java
--- parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java	8 Jan 2004 16:57:54 -0000	1.46
+++ parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java	8 Jan 2004 22:58:23 -0000
@@ -1116,6 +1116,51 @@
 			assertTrue( ((IASTFunction)i.next()).takesVarArgs() );
 	}
 	
+	public void testBug43110_XRef() throws Exception
+	{
+		StringBuffer buffer = new StringBuffer();
+		buffer.append( "void foo( ... ) {}\n" );
+		buffer.append( "void main( ){ foo( 1 ); }\n" );
+		
+		Iterator i = parse( buffer.toString() ).getDeclarations();
+		IASTFunction foo = (IASTFunction)i.next();
+		assertTrue( foo.takesVarArgs() );
+		assertAllReferences( 1, createTaskList( new Task( foo ) ) );
+
+		buffer = new StringBuffer();
+		buffer.append( "void foo( ... )   {}\n" );
+		buffer.append( "void foo( int x ) {}\n" );
+		buffer.append( "void main( ){ foo( 1 ); }\n" );
+		
+		i = parse( buffer.toString() ).getDeclarations();
+		IASTFunction foo1 = (IASTFunction)i.next();
+		IASTFunction foo2 = (IASTFunction)i.next();
+		assertTrue( foo1.takesVarArgs() );
+		assertFalse( foo2.takesVarArgs() );
+		assertAllReferences( 1, createTaskList( new Task( foo2 ) ) );
+		
+		buffer = new StringBuffer();
+		buffer.append( "void foo( ... )      {}\n" );
+		buffer.append( "void foo( int x = 1) {}\n" );
+		buffer.append( "void main( ){ foo(); }\n" );
+		
+		i = parse( buffer.toString() ).getDeclarations();
+		foo1 = (IASTFunction)i.next();
+		foo2 = (IASTFunction)i.next();
+		assertTrue( foo1.takesVarArgs() );
+		assertFalse( foo2.takesVarArgs() );
+		assertAllReferences( 1, createTaskList( new Task( foo2 ) ) );
+		
+		buffer = new StringBuffer();
+		buffer.append( "void foo( int x ... ) {}\n" );
+		buffer.append( "void main( ){ foo( 1, 2, 'a' ); }\n" );
+		
+		i = parse( buffer.toString() ).getDeclarations();
+		foo = (IASTFunction)i.next();
+		assertTrue( foo.takesVarArgs() );
+		assertAllReferences( 1, createTaskList( new Task( foo ) ) );
+	}
+	
 	public void testBug48307_FriendFunction_1() throws Exception {
 		StringWriter writer = new StringWriter();
 		writer.write( "class A{ public : void foo(); }; " );
Index: parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
===================================================================
retrieving revision 1.28
diff -u -r1.28 ParserSymbolTableTest.java
--- parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	17 Dec 2003 20:51:30 -0000	1.28
+++ parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	8 Jan 2004 22:58:26 -0000
@@ -3355,5 +3355,83 @@
 		assertTrue( results.contains( a3_int ) );
 	};
 	
+	/**
+	 * void foo( ... ){ }
+	 * 
+	 * foo( 1 );
+	 *  
+	 * @throws Exception
+	 */
+	public void testBug43110_Ellipses() throws Exception{
+		newTable();
+		
+		IParameterizedSymbol foo = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+		foo.setHasVariableArgs( true );
+		
+		table.getCompilationUnit().addSymbol( foo );
+		
+		List params = new LinkedList();
+		
+		TypeInfo p1 = new TypeInfo( TypeInfo.t_int, 0, null );
+		params.add( p1 );
+		
+		ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
+		
+		assertEquals( foo, look );
+	}
+	
+	/**
+	 * void foo( ... )   {}; //#1
+	 * void foo( int i ) {}; //#2
+	 * 
+	 * foo( 1 );  // calls foo #2
+	 * @throws Exception
+	 */
+	public void testBug43110_EllipsesRanking() throws Exception{
+		newTable();
+		
+		IParameterizedSymbol foo1 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+		foo1.setHasVariableArgs( true );
+		
+		table.getCompilationUnit().addSymbol( foo1 );
+		
+		IParameterizedSymbol foo2 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+		foo2.addParameter( TypeInfo.t_int, 0, null, false );
+		table.getCompilationUnit().addSymbol( foo2 );
+		
+		List params = new LinkedList();
+		
+		TypeInfo p1 = new TypeInfo( TypeInfo.t_int, 0, null );
+		params.add( p1 );
+		
+		ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
+		
+		assertEquals( foo2, look );
+	}
+	
+	/**
+	 * void foo( int i = 0 ) {};  //#1
+	 * void foo( ... ) {};        //#2
+	 * 
+	 * foo(); //calls #1
+	 * @throws Exception
+	 */
+	public void testBug43110_ElipsesRanking_2() throws Exception{
+		newTable();
+		
+		IParameterizedSymbol foo1 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+		foo1.addParameter( TypeInfo.t_int, 0, null, true );
+		table.getCompilationUnit().addSymbol( foo1 );
+		
+		IParameterizedSymbol foo2 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
+		foo2.setHasVariableArgs( true );
+		table.getCompilationUnit().addSymbol( foo2 );
+		
+		List params = new LinkedList();
+		
+		ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
+		
+		assertEquals( foo1, look );
+	}
 }
 

Back to the top