From b53b2d419c2204e3418bdfe5e90b50a306173cf0 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Mon, 7 Apr 2003 21:43:01 +0000 Subject: [PATCH] Patch for Andrew Niefer: - Rewrote the conversion sequence ranking to better handle all cases. - Added ParserSymbolTableTest::testOverloadRanking (whose initial failure prompted the ranking rewrite). --- core/org.eclipse.cdt.core/parser/ChangeLog | 3 + .../core/parser/ParserSymbolTable.java | 368 +++++++++++------- .../parser/ParserSymbolTableException.java | 2 +- .../internal/core/parser/util/TypeInfo.java | 32 +- core/org.eclipse.cdt.ui.tests/ChangeLog | 3 + .../parser/tests/ParserSymbolTableTest.java | 99 ++++- 6 files changed, 359 insertions(+), 148 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index 18f8e9b23d3..8c885ec450a 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -1,3 +1,6 @@ +2003-04-06 Andrew Niefer + Added ParserSymbolTable::Cost and used it to fix up the conversion sequence ranking + 2003-04-04 John Camelon Fixed defect 36073. Fixed error handling for unterminated strings in Scanner. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java index fc14e713494..39f1492bd5d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java @@ -810,7 +810,7 @@ public class ParserSymbolTable { if( decl == temp && ( type.checkBit( TypeInfo.isStatic ) || type.isType( TypeInfo.t_enumerator ) ) ){ temp = null; } else { - throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) ); + throw( new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ) ); } } @@ -969,14 +969,14 @@ public class ParserSymbolTable { if( cls == null ) { cls = decl; } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ); + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); } } else { //an object, can only have one of these if( obj == null ){ obj = decl; } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ); + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); } } } @@ -1030,7 +1030,7 @@ public class ParserSymbolTable { } if( ambiguous ){ - throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ); + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); } else { return cls; } @@ -1051,14 +1051,14 @@ public class ParserSymbolTable { } else if ( numFns == 1 ){ return (Declaration)functions.getFirst(); } else{ - throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ); + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); } } Declaration bestFn = null; //the best function Declaration currFn = null; //the function currently under consideration - int [] bestFnCost = null; //the cost of the best function - int [] currFnCost = null; //the cost for the current function + Cost [] bestFnCost = null; //the cost of the best function + Cost [] currFnCost = null; //the cost for the current function Iterator iterFns = functions.iterator(); Iterator sourceParams = null; @@ -1066,11 +1066,17 @@ public class ParserSymbolTable { int numTargetParams = 0; int numParams = 0; - int cost, temp, comparison; + int comparison; + Cost cost = null; + Cost temp = null; TypeInfo source = null; TypeInfo target = null; + boolean hasWorse; + boolean hasBetter; + boolean ambiguous = false; + for( int i = numFns; i > 0; i-- ){ currFn = (Declaration) iterFns.next(); @@ -1086,7 +1092,7 @@ public class ParserSymbolTable { numParams = ( numTargetParams < numSourceParams ) ? numTargetParams : numSourceParams; if( currFnCost == null ){ - currFnCost = new int [ numParams ]; + currFnCost = new Cost [ numParams ]; } comparison = 0; @@ -1095,47 +1101,58 @@ public class ParserSymbolTable { source = ( TypeInfo )sourceParams.next(); target = ( TypeInfo )targetParams.next(); if( source.equals( target ) ){ - cost = 0; //exact match, no cost + cost = new Cost( source, target ); + cost.rank = 0; //exact match, no cost } else { cost = checkStandardConversionSequence( source, target ); - if( cost == -1){ - cost = checkUserDefinedConversionSequence( source, target ); + if( cost.rank == -1){ + temp = checkUserDefinedConversionSequence( source, target ); + if( temp != null ){ + cost = temp; + } } } currFnCost[ j ] = cost; - - //compare successes against the best function - //comparison = (-1 = worse, 0 = same, 1 = better ) - if( cost >= 0 ){ - if( bestFnCost != null ){ - if( cost < bestFnCost[ j ] ){ - comparison = 1; //better - } else if ( cost > bestFnCost[ j ] ){ - comparison = -1; //worse - break; //don't bother continuing if worse - } - - } else { - comparison = 1; - } - } else { - comparison = -1; - } } - if( comparison > 0){ - //the current function is better than the previous best - bestFnCost = currFnCost; - currFnCost = null; - bestFn = currFn; - } else if( comparison == 0 ){ - //this is just as good as the best one, which means the best one isn't the best - bestFn = null; + + hasWorse = false; + hasBetter = false; + + for( int j = 0; j < numParams; j++ ){ + if( currFnCost[ j ].rank < 0 ){ + hasWorse = true; + hasBetter = false; + break; + } + + if( bestFnCost != null ){ + comparison = currFnCost[ j ].compare( bestFnCost[ j ] ); + hasWorse |= ( comparison < 0 ); + hasBetter |= ( comparison > 0 ); + } else { + hasBetter = true; + } + } + + ambiguous |= ( hasWorse && hasBetter ) || ( !hasWorse && !hasBetter ); + + if( !hasWorse ){ + if( hasBetter ){ + ambiguous = false; + bestFnCost = currFnCost; + currFnCost = null; + bestFn = currFn; + } } } - + + if( ambiguous ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); + } + return bestFn; } @@ -1363,7 +1380,29 @@ public class ParserSymbolTable { return okToAdd; } + + static private Cost lvalue_to_rvalue( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException{ + //lvalues will have type t_type + if( source.isType( TypeInfo.t_type ) ){ + source = getFlatTypeInfo( source ); + } + Cost cost = new Cost( source, target ); + + return cost; + } + + static private void qualificationConversion( Cost cost ){ + if( cost.source.getCVQualifier() == cost.target.getCVQualifier() || + ( cost.target.getCVQualifier() - cost.source.getCVQualifier()) > 1 ) + { + cost.qualification = cost.target.getCVQualifier() + 1; + cost.rank = 0; + } else { + cost.qualification = 0; + } + } + /** * * @param source @@ -1378,27 +1417,31 @@ public class ParserSymbolTable { * 4.5-4 bool can be promoted to int * 4.6 float can be promoted to double */ - static private int canPromote( TypeInfo source, TypeInfo target ){ - - //if they are the same, no promotion is necessary - if( ( source.isType( TypeInfo.t_bool, TypeInfo.t_double ) || - source.isType( TypeInfo.t_enumeration ) ) && - source.getType() == target.getType() ) + static private void promotion( Cost cost ){ + TypeInfo src = cost.source; + TypeInfo trg = cost.target; + + int mask = TypeInfo.isShort | TypeInfo.isLong | TypeInfo.isUnsigned; + + if( (src.isType( TypeInfo.t_bool, TypeInfo.t_float ) || src.isType( TypeInfo.t_enumeration )) && + (trg.isType( TypeInfo.t_int ) || trg.isType( TypeInfo.t_double )) ) { - return 0; - } - - if( source.isType( TypeInfo.t_enumeration ) || source.isType( TypeInfo.t_bool, TypeInfo.t_int ) ){ - if( target.isType( TypeInfo.t_int ) && target.canHold( source ) ){ - return 1; + if( src.getType() == trg.getType() && (( src.getTypeInfo() & mask) == (trg.getTypeInfo() & mask)) ){ + //same, no promotion needed + return; } - } else if( source.isType( TypeInfo.t_float ) ){ - if( target.isType( TypeInfo.t_double ) ){ - return 1; + + if( src.isType( TypeInfo.t_float ) ){ + cost.promotion = trg.isType( TypeInfo.t_double ) ? 1 : 0; + } else { + cost.promotion = ( trg.isType( TypeInfo.t_int ) && trg.canHold( src ) ) ? 1 : 0; } + + } else { + cost.promotion = 0; } - return -1; + cost.rank = (cost.promotion > 0 ) ? 1 : -1; } /** @@ -1408,104 +1451,106 @@ public class ParserSymbolTable { * @return int * */ - static private int canConvert(TypeInfo source, TypeInfo target ) throws ParserSymbolTableException{ - int temp = 0; + static private void conversion( Cost cost ){ + TypeInfo src = cost.source; + TypeInfo trg = cost.target; - source = getFlatTypeInfo( source ); + int temp; - String sourcePtr = source.getPtrOperator(); - String targetPtr = target.getPtrOperator(); + String tempStr = src.getPtrOperator(); + String srcPtr = ( tempStr == null ) ? new String("") : tempStr; - if( sourcePtr != null && sourcePtr.equals("") ){ - sourcePtr = null; - } - if( targetPtr != null && targetPtr.equals("") ){ - targetPtr = null; - } + tempStr = trg.getPtrOperator(); + String trgPtr = ( tempStr == null ) ? new String("") : tempStr; - boolean samePtrOp = ( ( sourcePtr == targetPtr ) || - ( sourcePtr != null && targetPtr != null && sourcePtr.equals( targetPtr ) ) ); - //are they the same? - if( source.getType() == target.getType() && - source.getTypeDeclaration() == target.getTypeDeclaration() && - samePtrOp ) - { - return 0; - } + cost.conversion = 0; + cost.detail = 0; - //no go if they have different pointer qualification - if( !samePtrOp ) - { - return -1; - } - - //TBD, do a better check on the kind of ptrOperator - if( sourcePtr == null || !sourcePtr.equals("*") ){ - //4.7 An rvalue of an integer type can be converted to an rvalue of another integer type. - //An rvalue of an enumeration type can be converted to an rvalue of an integer type. - if( source.isType( TypeInfo.t_bool, TypeInfo.t_int ) || - source.isType( TypeInfo.t_float, TypeInfo.t_double ) || - source.isType( TypeInfo.t_enumeration ) ) - { - if( target.isType( TypeInfo.t_bool, TypeInfo.t_int ) || - target.isType( TypeInfo.t_float, TypeInfo.t_double ) ) - { - return 2; - } - } - } else /*pointers*/ { - Declaration sourceDecl = source.getTypeDeclaration(); - Declaration targetDecl = target.getTypeDeclaration(); + if( !srcPtr.equals( trgPtr ) ){ + return; + } + if( srcPtr.equals("*") ){ + Declaration srcDecl = src.isType( TypeInfo.t_type ) ? src.getTypeDeclaration() : null; + Declaration trgDecl = trg.isType( TypeInfo.t_type ) ? trg.getTypeDeclaration() : null; + if( srcDecl == null || (trgDecl == null && !trg.isType( TypeInfo.t_void )) ){ + return; + } + //4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be //converted to an rvalue of type "pointer to cv void" - if( source.isType( TypeInfo.t_type ) && target.isType( TypeInfo.t_void ) ){ - //use cost of MAX_VALUE since conversion to any base class, no matter how - //far away, would be better than conversion to void - return Integer.MAX_VALUE; - } + if( trg.isType( TypeInfo.t_void ) ){ + cost.rank = 2; + cost.conversion = 1; + cost.detail = 2; + return; + } + + cost.detail = 1; + //4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted // to an rvalue of type "pointer to cv B", where B is a base class of D. - else if( source.isType( TypeInfo.t_type ) && sourceDecl.isType( TypeInfo.t_class ) && - target.isType( TypeInfo.t_type ) && targetDecl.isType( TypeInfo.t_class ) ) - { - temp = hasBaseClass( sourceDecl, targetDecl ); - return ( temp > -1 ) ? 1 + temp : -1; + if( srcDecl.isType( TypeInfo.t_class ) && trgDecl.isType( TypeInfo.t_class ) ){ + temp = hasBaseClass( srcDecl, trgDecl ); + cost.rank = 2; + cost.conversion = ( temp > -1 ) ? temp : 0; + cost.detail = 1; + return; } + //4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type, //can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a //derived class of B - else if( ( source.isType( TypeInfo.t_type ) && sourceDecl._containingScope.isType( TypeInfo.t_class ) ) || - ( target.isType( TypeInfo.t_type ) && targetDecl._containingScope.isType( TypeInfo.t_class ) ) ) + if( srcDecl._containingScope.isType( TypeInfo.t_class ) && trgDecl._containingScope.isType( TypeInfo.t_class ) ){ + temp = hasBaseClass( trgDecl._containingScope, srcDecl._containingScope ); + cost.rank = 2; + cost.conversion = ( temp > -1 ) ? temp : 0; + return; + } + } else { + //4.7 An rvalue of an integer type can be converted to an rvalue of another integer type. + //An rvalue of an enumeration type can be converted to an rvalue of an integer type. + if( src.isType( TypeInfo.t_bool, TypeInfo.t_int ) || + src.isType( TypeInfo.t_float, TypeInfo.t_double ) || + src.isType( TypeInfo.t_enumeration ) ) { - temp = hasBaseClass( targetDecl._containingScope, sourceDecl._containingScope ); - return ( temp > -1 ) ? 1 + temp : -1; + if( trg.isType( TypeInfo.t_bool, TypeInfo.t_int ) || + trg.isType( TypeInfo.t_float, TypeInfo.t_double ) ) + { + cost.rank = 2; + cost.conversion = 1; + } } } - - return -1; } - static private int checkStandardConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException { - int cost = -1; - int temp = 0; + static private Cost checkStandardConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException { + Cost cost = lvalue_to_rvalue( source, target ); - if( !canDoQualificationConversion( source, target ) ){ - //matching qualification is at no cost, but not matching is a failure - cost = -1; - } else if( (temp = canPromote( source, target )) >= 0 ){ - cost = temp; - } else if( (temp = canConvert( source, target )) >= 0 ){ - cost = temp; //cost for conversion has to do with "distance" between source and target - } else { - cost = -1; //failure + if( cost.source.equals( cost.target ) ){ + cost.rank = 1; + return cost; } + + qualificationConversion( cost ); + + //if we can't convert the qualifications, then we can't do anything + if( cost.qualification == 0 ){ + return cost; + } + + promotion( cost ); + if( cost.promotion > 0 || cost.rank > -1 ){ + return cost; + } + + conversion( cost ); return cost; } - static private int checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException { - int cost = -1; + static private Cost checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException { + Cost cost = null; Declaration targetDecl = null; Declaration constructor = null; @@ -1520,21 +1565,13 @@ public class ParserSymbolTable { constructor = ResolveAmbiguities( data ); if( constructor != null ){ cost = checkStandardConversionSequence( new TypeInfo( TypeInfo.t_type, constructor._containingScope ), target ); - if( cost != -1 ){ - cost++; - } } } } return cost; } - - static private boolean canDoQualificationConversion( TypeInfo source, TypeInfo target ){ - return ( source.getCVQualifier() == source.getCVQualifier() || - (source.getCVQualifier() - source.getCVQualifier()) > 1 ); - } - + /** * * @param decl @@ -1563,8 +1600,13 @@ public class ParserSymbolTable { info = info.getTypeDeclaration().getTypeInfo(); } - returnInfo.setType( TypeInfo.t_type ); - returnInfo.setTypeDeclaration( typeDecl ); + if( info.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){ + returnInfo.setType( TypeInfo.t_type ); + returnInfo.setTypeDeclaration( typeDecl ); + } else { + returnInfo.setTypeInfo( info.getTypeInfo() ); + returnInfo.setTypeDeclaration( null ); + } String ptrOp = returnInfo.getPtrOperator(); returnInfo.setPtrOperator( topInfo.getInvertedPtrOperator() ); @@ -1572,11 +1614,16 @@ public class ParserSymbolTable { if( ptrOp != null ){ returnInfo.addPtrOperator( ptrOp ); } + + returnInfo.setCVQualifier( info.getCVQualifier() ); + returnInfo.addCVQualifier( topInfo.getCVQualifier() ); } return returnInfo; } + + private Stack _contextStack = new Stack(); private Declaration _compilationUnit; @@ -1605,4 +1652,47 @@ public class ParserSymbolTable { type = t; } } + + static private class Cost + { + public Cost( TypeInfo s, TypeInfo t ){ + source = s; + target = t; + } + + public TypeInfo source; + public TypeInfo target; + + public int lvalue; + public int promotion; + public int conversion; + public int qualification; + + public int rank = -1; + public int detail; + + public int compare( Cost cost ){ + int result = 0; + + if( promotion > 0 || cost.promotion > 0 ){ + result = cost.promotion - promotion; + } + if( conversion > 0 || cost.conversion > 0 ){ + if( detail == cost.detail ){ + result = cost.conversion - conversion; + } else { + result = cost.detail - detail; + } + } + + if( result == 0 ){ + result = cost.qualification - qualification; + } + + return result; + } + + + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java index 89fc8e1bc33..3efbcce0646 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java @@ -37,7 +37,7 @@ public class ParserSymbolTableException extends Exception { } public static final int r_Unspecified = -1; - public static final int r_AmbiguousName = 0; + public static final int r_Ambiguous = 0; public static final int r_BadTypeInfo = 1; public static final int r_CircularInheritance = 2; public static final int r_InvalidOverload = 3; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java index 30c4a72cb3d..4986e4c96cf 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java @@ -96,9 +96,9 @@ public class TypeInfo{ // none < const volatile // const < const volatile // volatile < const volatile - public static final int cvConst = 1; - public static final int cvVolatile = 2; - public static final int cvConstVolatile = 4; + public static final int cvConst = 2; + public static final int cvVolatile = 3; + public static final int cvConstVolatile = 5; // Convenience methods public void setBit(boolean b, int mask){ @@ -130,6 +130,14 @@ public class TypeInfo{ return isType( type, 0 ); } + public int getTypeInfo(){ + return _typeInfo; + } + + public void setTypeInfo( int typeInfo ){ + _typeInfo = typeInfo; + } + /** * * @param type @@ -308,6 +316,24 @@ public class TypeInfo{ return getType() >= type.getType(); } + public boolean equals( Object t ){ + if( t == null || !(t instanceof TypeInfo) ){ + return false; + } + + TypeInfo type = (TypeInfo)t; + + boolean result = ( _typeInfo == type._typeInfo ); + result &= ( _typeDeclaration == type._typeDeclaration ); + result &= ( _cvQualifier == type._cvQualifier ); + + String op1 = ( _ptrOperator != null && _ptrOperator.equals("") ) ? null : _ptrOperator; + String op2 = ( type._ptrOperator != null && type._ptrOperator.equals("") ) ? null : type._ptrOperator; + result &= (( op1 != null && op2 != null && op1.equals( op2 ) ) || op1 == op2 ); + + return result; + } + private int _typeInfo = 0; private Declaration _typeDeclaration; private int _cvQualifier = 0; diff --git a/core/org.eclipse.cdt.ui.tests/ChangeLog b/core/org.eclipse.cdt.ui.tests/ChangeLog index e4593c20a3e..77e457d536a 100644 --- a/core/org.eclipse.cdt.ui.tests/ChangeLog +++ b/core/org.eclipse.cdt.ui.tests/ChangeLog @@ -1,3 +1,6 @@ +2003-04-06 Andrew Niefer + Added ParserSymbolTableTest::testOverloadRanking() + 2003-04-04 Alain Magloire * src/org/eclipse/cdt/testplugin/util/VerifyDialog.java: Remove some warnings. diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java index 146fc03deba..e291be7ea40 100644 --- a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java +++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java @@ -349,7 +349,7 @@ public class ParserSymbolTableTest extends TestCase { assertTrue( false ); } catch( ParserSymbolTableException e){ - assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName ); + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); } } @@ -426,7 +426,7 @@ public class ParserSymbolTableTest extends TestCase { assertTrue( false ); } catch ( ParserSymbolTableException e){ - assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName ); + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); } } @@ -645,7 +645,7 @@ public class ParserSymbolTableTest extends TestCase { catch ( ParserSymbolTableException e ) { //ambiguous B::C::i and A::i - assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName ); + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); } table.pop(); //end f2 table.pop(); //end nsD @@ -729,7 +729,7 @@ public class ParserSymbolTableTest extends TestCase { catch ( ParserSymbolTableException e ) { //ambiguous, both M::i and N::i are visible. - assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName ); + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); } look = table.LookupNestedNameSpecifier("N"); @@ -1023,7 +1023,7 @@ public class ParserSymbolTableTest extends TestCase { look = table.QualifiedLookup( "y" ); assertTrue(false); } catch ( ParserSymbolTableException e ) { - assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName ); + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); } } @@ -1813,5 +1813,94 @@ public class ParserSymbolTableTest extends TestCase { Declaration look = table.UnqualifiedFunctionLookup( "f", paramList ); assertEquals( look, f ); } + + /** + * + * @throws Exception + * + * void f( const int *, short ); + * void f( int *, int ); + * + * int i; + * short s; + * + * void main() { + * f( &i, s ); //ambiguous because &i->int* is better than &i->const int * + * //but s-> short is better than s->int + * f( &i, 1L ); //calls f(int *, int) because &i->int* is better than &i->const int * + * //and 1L->short and 1L->int are indistinguishable + * f( &i, 'c' ); //calls f( int*, int) because &i->int * is better than &i->const int * + * //and c->int is better than c->short + * f( (const)&i, 1L ); //calls f(const int *, short ) because const &i->int* is better than &i->int * + * //and 1L->short and 1L->int are indistinguishable + * } + */ + public void testOverloadRanking() throws Exception{ + newTable(); + + Declaration f1 = new Declaration( "f" ); + f1.setType( TypeInfo.t_function ); + f1.addParameter( TypeInfo.t_int, TypeInfo.cvConst, "*", false ); + f1.addParameter( TypeInfo.t_int | TypeInfo.isShort, 0, null, false ); + + table.addDeclaration( f1 ); + + Declaration f2 = new Declaration( "f" ); + f2.setType( TypeInfo.t_function ); + f2.addParameter( TypeInfo.t_int, 0, "*", false ); + f2.addParameter( TypeInfo.t_int, 0, null, false ); + table.addDeclaration( f2 ); + + Declaration i = new Declaration( "i" ); + i.setType( TypeInfo.t_int ); + table.addDeclaration( i ); + + Declaration s = new Declaration( "s" ); + s.setType( TypeInfo.t_int ); + s.getTypeInfo().setBit( true, TypeInfo.isShort ); + table.addDeclaration( s ); + + Declaration main = new Declaration( "main" ); + main.setType( TypeInfo.t_function ); + table.addDeclaration( main ); + table.push( main ); + + LinkedList params = new LinkedList(); + TypeInfo p1 = new TypeInfo( TypeInfo.t_type, i, 0, "&", false ); + TypeInfo p2 = new TypeInfo( TypeInfo.t_type, s, 0, null, false ); + params.add( p1 ); + params.add( p2 ); + + Declaration look = null; + + try{ + look = table.UnqualifiedFunctionLookup( "f", params ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); + } + + params.clear(); + TypeInfo p3 = new TypeInfo( TypeInfo.t_int | TypeInfo.isLong, null, 0, null, false ); + params.add( p1 ); + params.add( p3 ); + look = table.UnqualifiedFunctionLookup( "f", params ); + assertEquals( look, f2 ); + + params.clear(); + TypeInfo p4 = new TypeInfo( TypeInfo.t_char, null, 0, null, false ); + params.add( p1 ); + params.add( p4 ); + look = table.UnqualifiedFunctionLookup( "f", params ); + assertEquals( look, f2 ); + + params.clear(); + p1.setCVQualifier( TypeInfo.cvConst ); + params.add( p1 ); + params.add( p3 ); + look = table.UnqualifiedFunctionLookup( "f", params ); + assertEquals( look, f1 ); + + } }