mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-03 22:35:43 +02:00
Patch for Andrew Niefer:
patch_04.08.03(cdt.core).txt user defined conversions by operator patch_04.08.04(cdt.ui.tests).txt added ParserSymbolTableTest::testUserDefinedConversionByOperator()
This commit is contained in:
parent
cc325e9b5f
commit
ef5944b36b
3 changed files with 227 additions and 13 deletions
|
@ -1037,7 +1037,7 @@ public class ParserSymbolTable {
|
|||
}
|
||||
|
||||
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 @@ public class ParserSymbolTable {
|
|||
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 @@ public class ParserSymbolTable {
|
|||
break;
|
||||
}
|
||||
|
||||
currHasAmbiguousParam = ( currFnCost[ j ].userDefined == 1 );
|
||||
|
||||
if( bestFnCost != null ){
|
||||
comparison = currFnCost[ j ].compare( bestFnCost[ j ] );
|
||||
hasWorse |= ( comparison < 0 );
|
||||
|
@ -1143,13 +1147,14 @@ public class ParserSymbolTable {
|
|||
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 @@ public class ParserSymbolTable {
|
|||
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 @@ public class ParserSymbolTable {
|
|||
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 @@ public class ParserSymbolTable {
|
|||
|
||||
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 @@ public class ParserSymbolTable {
|
|||
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 class ParserSymbolTable {
|
|||
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 @@ public class ParserSymbolTable {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -90,6 +90,23 @@ public class TypeInfo{
|
|||
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 @@ public class TypeInfo{
|
|||
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;
|
||||
|
|
|
@ -1902,5 +1902,108 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue