mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Patch for Andrew Niefer:
- Rewrote the conversion sequence ranking to better handle all cases. - Added ParserSymbolTableTest::testOverloadRanking (whose initial failure prompted the ranking rewrite).
This commit is contained in:
parent
e92be51ca5
commit
b53b2d419c
6 changed files with 359 additions and 148 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue