mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-07 00:05:53 +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
|
@ -1073,9 +1073,11 @@ public class ParserSymbolTable {
|
||||||
TypeInfo source = null;
|
TypeInfo source = null;
|
||||||
TypeInfo target = null;
|
TypeInfo target = null;
|
||||||
|
|
||||||
boolean hasWorse;
|
boolean hasWorse = false;
|
||||||
boolean hasBetter;
|
boolean hasBetter = false;
|
||||||
boolean ambiguous = false;
|
boolean ambiguous = false;
|
||||||
|
boolean currHasAmbiguousParam = false;
|
||||||
|
boolean bestHasAmbiguousParam = false;
|
||||||
|
|
||||||
for( int i = numFns; i > 0; i-- ){
|
for( int i = numFns; i > 0; i-- ){
|
||||||
currFn = (Declaration) iterFns.next();
|
currFn = (Declaration) iterFns.next();
|
||||||
|
@ -1128,6 +1130,8 @@ public class ParserSymbolTable {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currHasAmbiguousParam = ( currFnCost[ j ].userDefined == 1 );
|
||||||
|
|
||||||
if( bestFnCost != null ){
|
if( bestFnCost != null ){
|
||||||
comparison = currFnCost[ j ].compare( bestFnCost[ j ] );
|
comparison = currFnCost[ j ].compare( bestFnCost[ j ] );
|
||||||
hasWorse |= ( comparison < 0 );
|
hasWorse |= ( comparison < 0 );
|
||||||
|
@ -1143,13 +1147,14 @@ public class ParserSymbolTable {
|
||||||
if( hasBetter ){
|
if( hasBetter ){
|
||||||
ambiguous = false;
|
ambiguous = false;
|
||||||
bestFnCost = currFnCost;
|
bestFnCost = currFnCost;
|
||||||
|
bestHasAmbiguousParam = currHasAmbiguousParam;
|
||||||
currFnCost = null;
|
currFnCost = null;
|
||||||
bestFn = currFn;
|
bestFn = currFn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ambiguous ){
|
if( ambiguous || bestHasAmbiguousParam ){
|
||||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
|
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1387,6 +1392,23 @@ public class ParserSymbolTable {
|
||||||
source = getFlatTypeInfo( source );
|
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 );
|
Cost cost = new Cost( source, target );
|
||||||
|
|
||||||
return cost;
|
return cost;
|
||||||
|
@ -1528,7 +1550,7 @@ public class ParserSymbolTable {
|
||||||
Cost cost = lvalue_to_rvalue( source, target );
|
Cost cost = lvalue_to_rvalue( source, target );
|
||||||
|
|
||||||
if( cost.source.equals( cost.target ) ){
|
if( cost.source.equals( cost.target ) ){
|
||||||
cost.rank = 1;
|
cost.rank = 0;
|
||||||
return cost;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1551,9 +1573,15 @@ public class ParserSymbolTable {
|
||||||
|
|
||||||
static private Cost checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException {
|
static private Cost checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException {
|
||||||
Cost cost = null;
|
Cost cost = null;
|
||||||
Declaration targetDecl = null;
|
Cost constructorCost = null;
|
||||||
Declaration constructor = null;
|
Cost conversionCost = null;
|
||||||
|
|
||||||
|
Declaration targetDecl = null;
|
||||||
|
Declaration sourceDecl = null;
|
||||||
|
Declaration constructor = null;
|
||||||
|
Declaration conversion = null;
|
||||||
|
|
||||||
|
//constructors
|
||||||
if( target.getType() == TypeInfo.t_type ){
|
if( target.getType() == TypeInfo.t_type ){
|
||||||
targetDecl = target.getTypeDeclaration();
|
targetDecl = target.getTypeDeclaration();
|
||||||
if( targetDecl.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
|
if( targetDecl.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
|
||||||
|
@ -1563,12 +1591,54 @@ public class ParserSymbolTable {
|
||||||
data.parameters = params;
|
data.parameters = params;
|
||||||
LookupInContained( data, targetDecl );
|
LookupInContained( data, targetDecl );
|
||||||
constructor = ResolveAmbiguities( data );
|
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;
|
return cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1667,13 +1737,31 @@ public class ParserSymbolTable {
|
||||||
public int promotion;
|
public int promotion;
|
||||||
public int conversion;
|
public int conversion;
|
||||||
public int qualification;
|
public int qualification;
|
||||||
|
public int userDefined;
|
||||||
public int rank = -1;
|
public int rank = -1;
|
||||||
public int detail;
|
public int detail;
|
||||||
|
|
||||||
public int compare( Cost cost ){
|
public int compare( Cost cost ){
|
||||||
int result = 0;
|
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 ){
|
if( promotion > 0 || cost.promotion > 0 ){
|
||||||
result = cost.promotion - promotion;
|
result = cost.promotion - promotion;
|
||||||
}
|
}
|
||||||
|
@ -1691,8 +1779,6 @@ public class ParserSymbolTable {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,23 @@ public class TypeInfo{
|
||||||
public static final int t_void = 14;
|
public static final int t_void = 14;
|
||||||
public static final int t_enumerator = 15;
|
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 :
|
//Partial ordering :
|
||||||
// none < const
|
// none < const
|
||||||
// none < volatile
|
// none < volatile
|
||||||
|
@ -334,6 +351,14 @@ public class TypeInfo{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString(){
|
||||||
|
if( isType( t_type ) ){
|
||||||
|
return _typeDeclaration.getName();
|
||||||
|
} else {
|
||||||
|
return _image[ getType() ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int _typeInfo = 0;
|
private int _typeInfo = 0;
|
||||||
private Declaration _typeDeclaration;
|
private Declaration _typeDeclaration;
|
||||||
private int _cvQualifier = 0;
|
private int _cvQualifier = 0;
|
||||||
|
|
|
@ -1902,5 +1902,108 @@ public class ParserSymbolTableTest extends TestCase {
|
||||||
assertEquals( look, f1 );
|
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