Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Parser Symbol Table Patch - user defined conversions by operator

patch_04.08.03(cdt.core).txt
	user defined conversions by operator

patch_04.08.04(cdt.ui.tests).txt
	added ParserSymbolTableTest::testUserDefinedConversionByOperator()

-Andrew

Index: parser/ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/ChangeLog,v
retrieving revision 1.22
diff -u -r1.22 ChangeLog
--- parser/ChangeLog	7 Apr 2003 21:43:01 -0000	1.22
+++ parser/ChangeLog	8 Apr 2003 14:02:54 -0000
@@ -1,3 +1,6 @@
+2003-04-08 Andrew Niefer
+	Added User defined conversions via operator
+
 2003-04-06 Andrew Niefer
 	Added ParserSymbolTable::Cost and used it to fix up the conversion sequence ranking
 
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.9
diff -u -r1.9 ParserSymbolTable.java
--- parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	7 Apr 2003 21:43:01 -0000	1.9
+++ parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java	8 Apr 2003 14:02:55 -0000
@@ -1037,7 +1037,7 @@
 	}
 
 	static private Declaration ResolveFunction( LookupData data, LinkedList functions ) throws ParserSymbolTableException{
-		
+		 
 		ReduceToViable( data, functions );
 		
 		int numSourceParams = ( data.parameters == null ) ? 0 : data.parameters.size();
@@ -1073,10 +1073,12 @@
 		TypeInfo source = null;
 		TypeInfo target = null;
 		 
-		boolean hasWorse;
-		boolean hasBetter;
+		boolean hasWorse = false;
+		boolean hasBetter = false;
 		boolean ambiguous = false;
-		
+		boolean currHasAmbiguousParam = false;
+		boolean bestHasAmbiguousParam = false;
+
 		for( int i = numFns; i > 0; i-- ){
 			currFn = (Declaration) iterFns.next();
 			
@@ -1128,6 +1130,8 @@
 					break;
 				}
 				
+				currHasAmbiguousParam = ( currFnCost[ j ].userDefined == 1 );
+				
 				if( bestFnCost != null ){
 					comparison = currFnCost[ j ].compare( bestFnCost[ j ] );
 					hasWorse |= ( comparison < 0 );
@@ -1143,13 +1147,14 @@
 				if( hasBetter ){
 					ambiguous = false;
 					bestFnCost = currFnCost;
+					bestHasAmbiguousParam = currHasAmbiguousParam;
 					currFnCost = null;
 					bestFn = currFn;
 				}				
 			}
 		}
 
-		if( ambiguous ){
+		if( ambiguous || bestHasAmbiguousParam ){
 			throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
 		}
 						
@@ -1387,6 +1392,23 @@
 			source = getFlatTypeInfo( source );
 		}
 	
+		String sourcePtr = source.getPtrOperator();
+		String targetPtr = target.getPtrOperator();
+		
+		if( sourcePtr != null && sourcePtr.length() > 0 ){
+			char sourcePtrArray [] = sourcePtr.toCharArray();
+			if( sourcePtrArray[ 0 ] == '&' ){
+				source.setPtrOperator( new String(sourcePtrArray, 1, sourcePtr.length() - 1 ) );
+			}
+		}
+		
+		if( targetPtr != null && targetPtr.length() > 0 ){
+			char targetPtrArray [] = targetPtr.toCharArray();
+			if( targetPtrArray[ 0 ] == '&' ){
+				target.setPtrOperator ( new String( targetPtrArray, 1, targetPtr.length() - 1 ) );
+			}
+		}
+		
 		Cost cost = new Cost( source, target );
 	
 		return cost;
@@ -1528,7 +1550,7 @@
 		Cost cost = lvalue_to_rvalue( source, target );
 		
 		if( cost.source.equals( cost.target ) ){
-			cost.rank = 1;
+			cost.rank = 0;
 			return cost;
 		}
 	
@@ -1551,9 +1573,15 @@
 	
 	static private Cost checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException {
 		Cost cost = null;
+		Cost constructorCost = null;
+		Cost conversionCost = null;
+
 		Declaration targetDecl = null;
+		Declaration sourceDecl = null;
 		Declaration constructor = null;
+		Declaration conversion = null;
 		
+		//constructors
 		if( target.getType() == TypeInfo.t_type ){
 			targetDecl = target.getTypeDeclaration();
 			if( targetDecl.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
@@ -1563,12 +1591,54 @@
 				data.parameters = params;
 				LookupInContained( data, targetDecl );
 				constructor = ResolveAmbiguities( data );
-				if( constructor != null ){
-					cost = checkStandardConversionSequence( new TypeInfo( TypeInfo.t_type, constructor._containingScope ), target );
-				}
 			}
+		}
+		
+		//conversion operators
+		if( source.getType() == TypeInfo.t_type ){
+			source = getFlatTypeInfo( source );
+			sourceDecl = source.getTypeDeclaration();
 			
+			if( sourceDecl != null ){
+				String name = target.toString();
+				
+				if( !name.equals("") ){
+					LookupData data = new LookupData( "operator " + name, TypeInfo.t_function );
+					LinkedList params = new LinkedList();
+					data.parameters = params;
+					
+					LookupInContained( data, sourceDecl );
+					conversion = ResolveAmbiguities( data );	
+				}
+			}
+		}
+		
+		if( constructor != null ){
+			constructorCost = checkStandardConversionSequence( new TypeInfo( TypeInfo.t_type, constructor._containingScope ), target );
+		}
+		if( conversion != null ){
+			conversionCost = checkStandardConversionSequence( new TypeInfo( target.getType(), target.getTypeDeclaration() ), target );
+		}
+		
+		//if both are valid, then the conversion is ambiguous
+		if( constructorCost != null && constructorCost.rank != -1 && 
+			conversionCost != null && conversionCost.rank != -1 )
+		{
+			cost = constructorCost;
+			cost.userDefined = 1;
+			cost.rank = 3;
+		} else {
+			if( constructorCost != null && constructorCost.rank != -1 ){
+				cost = constructorCost;
+				cost.userDefined = constructor.hashCode();
+				cost.rank = 3;
+			} else if( conversionCost != null && conversionCost.rank != -1 ){
+				cost = conversionCost;
+				cost.userDefined = conversion.hashCode();
+				cost.rank = 3;
+			} 			
 		}
+		
 		return cost;
 	}
 
@@ -1667,13 +1737,31 @@
 		public int promotion;
 		public int conversion;
 		public int qualification;
-		
+		public int userDefined;
 		public int rank = -1;
 		public int detail;
 		
 		public int compare( Cost cost ){
 			int result = 0;
 			
+			if( rank != cost.rank ){
+				return cost.rank - rank;
+			}
+			
+			if( userDefined != 0 || cost.userDefined != 0 ){
+				if( userDefined == 0 || cost.userDefined == 0 ){
+					return cost.userDefined - userDefined;
+				} else {
+					if( (userDefined == 1 || cost.userDefined == 1) ||
+						(userDefined != cost.userDefined ) )
+					{
+						return 0;
+					} 
+					// else they are the same constructor/conversion operator and are ranked
+					//on the standard conversion sequence
+				}
+			}
+			
 			if( promotion > 0 || cost.promotion > 0 ){
 				result = cost.promotion - promotion;
 			}
@@ -1691,8 +1779,6 @@
 			 
 			return result;
 		}
-		
-		
 	}
-	
+
 }
Index: parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java,v
retrieving revision 1.3
diff -u -r1.3 TypeInfo.java
--- parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java	7 Apr 2003 21:43:01 -0000	1.3
+++ parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java	8 Apr 2003 14:02:55 -0000
@@ -90,6 +90,23 @@
 	public static final int t_void        = 14;
 	public static final int t_enumerator  = 15;
 		
+	private static final String _image[] = {	"", 
+												"", 
+												"namespace", 
+												"class", 
+												"struct", 
+												"union", 
+												"enum",
+												"",
+												"bool",
+												"char",
+												"wchar_t",
+												"int",
+												"float",
+												"double",
+												"void",
+												""
+											 };
 	//Partial ordering :
 	// none		< const
 	// none     < volatile
@@ -334,6 +351,14 @@
 		return result;
 	}
 	
+	public String toString(){
+		if( isType( t_type ) ){
+			return _typeDeclaration.getName();
+		} else {
+			return _image[ getType() ];
+		}
+	}
+
 	private int 		 _typeInfo = 0;
 	private Declaration _typeDeclaration;	
 	private int		 _cvQualifier = 0;
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui.tests/ChangeLog,v
retrieving revision 1.21
diff -u -r1.21 ChangeLog
--- ChangeLog	7 Apr 2003 21:42:56 -0000	1.21
+++ ChangeLog	8 Apr 2003 14:03:26 -0000
@@ -1,3 +1,6 @@
+2003-04-08 Andrew Niefer
+	Added ParserSymbolTableTest::testUserDefinedConversionByOperator()
+
 2003-04-06 Andrew Niefer
 	Added ParserSymbolTableTest::testOverloadRanking()
 
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.10
diff -u -r1.10 ParserSymbolTableTest.java
--- parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	7 Apr 2003 21:42:56 -0000	1.10
+++ parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java	8 Apr 2003 14:03:27 -0000
@@ -1902,5 +1902,108 @@
 		assertEquals( look, f1 );
 		
 	}
+	
+	/**
+	 * 
+	 * @throws Exception
+	 *
+	 * class B;
+	 * class A { A( B& ); };
+	 * class B { operator A(); };
+	 *  
+	 * void f(A){}
+	 * 
+	 * B b;
+	 * f( b );	//ambiguous because b->A via constructor or conversion
+	 *
+	 * class C { C( B& ); };
+	 *  
+	 * void f(C){}
+	 * 
+	 * f( b );	//ambiguous because b->C via constructor and b->a via constructor/conversion
+	 * 
+	 * void f(B){}
+	 * 
+	 * f( b );  //calls f(B) 
+	 */
+	   
+	public void testUserDefinedConversionByOperator() throws Exception{
+		newTable();
+		
+		Declaration B = new Declaration( "B" );
+		B.setType( TypeInfo.t_class );
+		
+		table.addDeclaration( B );
+		
+		Declaration A = new Declaration( "A" );
+		A.setType( TypeInfo.t_class );
+		table.addDeclaration( A );
+		
+		table.push( A );
+		Declaration constructA = new Declaration( "" );
+		constructA.setType( TypeInfo.t_function );
+		constructA.addParameter( B, 0, "&", false );
+		table.addDeclaration( constructA );
+		table.pop();
+		
+		table.push( B );
+		Declaration operator = new Declaration( "operator A" );
+		operator.setType( TypeInfo.t_function );
+		table.addDeclaration( operator );
+		table.pop();
+		
+		Declaration f1 = new Declaration( "f" );
+		f1.setType( TypeInfo.t_function );
+		f1.addParameter( A, 0, null, false );
+		table.addDeclaration( f1 );
+		
+		Declaration b = new Declaration( "b" );
+		b.setType( TypeInfo.t_type );
+		b.setTypeDeclaration( B );
+		
+		LinkedList params = new LinkedList();
+		TypeInfo p1 = new TypeInfo( TypeInfo.t_type, b, 0, null, false );
+		params.add( p1 );
+		
+		Declaration look = null;
+		
+		try{
+			look = table.UnqualifiedFunctionLookup( "f", params );
+			assertTrue( false );
+		} catch( ParserSymbolTableException e ){
+			assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); 
+		}
+		
+		Declaration C = new Declaration("C");
+		C.setType( TypeInfo.t_class );
+		table.addDeclaration( C );
+		
+		table.push( C );
+		Declaration constructC = new Declaration("");
+		constructC.setType( TypeInfo.t_function );
+		constructC.addParameter( B, 0, "&", false );
+		table.addDeclaration( constructC );
+		table.pop();
+		
+		Declaration f2 = new Declaration( "f" );
+		f2.setType( TypeInfo.t_function );
+		f2.addParameter(  C, 0, null, false );
+		table.addDeclaration( f2 );
+		
+		try{
+			look = table.UnqualifiedFunctionLookup( "f", params );
+			assertTrue( false );
+		} catch( ParserSymbolTableException e ){
+			assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); 
+		}
+		
+		Declaration f3 = new Declaration( "f" );
+		f3.setType( TypeInfo.t_function );
+		f3.addParameter(  B, 0, null, false );
+		table.addDeclaration( f3 );
+		
+		look = table.UnqualifiedFunctionLookup( "f", params );
+		assertEquals( look, f3 );
+	}
 }
 

Back to the top