mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-01 06:05:24 +02:00
Patch for Andrew Niefer.
Core: Added IParameterizedSymbol.setHasVariableArgs() & hasVariableArgs() Modified ParserSymbolTable.resolveFunction & reduceToViable Modified CompleteParseASTFactory.createMethod & createFunction Tests: Added CompleteParseASTTest.testBug43110_XRef Added ParserSymbolTableTest.testBug43110_Ellipses Added ParserSymbolTableTest.testBug43110_EllipsesRanking Added ParserSymbolTableTest.testBug43110_EllipsesRanking_2
This commit is contained in:
parent
7d3eaf190b
commit
51fc347c92
10 changed files with 2443 additions and 2274 deletions
File diff suppressed because it is too large
Load diff
|
@ -1116,6 +1116,51 @@ public class CompleteParseASTTest extends CompleteParseBaseTest
|
|||
assertTrue( ((IASTFunction)i.next()).takesVarArgs() );
|
||||
}
|
||||
|
||||
public void testBug43110_XRef() throws Exception
|
||||
{
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append( "void foo( ... ) {}\n" );
|
||||
buffer.append( "void main( ){ foo( 1 ); }\n" );
|
||||
|
||||
Iterator i = parse( buffer.toString() ).getDeclarations();
|
||||
IASTFunction foo = (IASTFunction)i.next();
|
||||
assertTrue( foo.takesVarArgs() );
|
||||
assertAllReferences( 1, createTaskList( new Task( foo ) ) );
|
||||
|
||||
buffer = new StringBuffer();
|
||||
buffer.append( "void foo( ... ) {}\n" );
|
||||
buffer.append( "void foo( int x ) {}\n" );
|
||||
buffer.append( "void main( ){ foo( 1 ); }\n" );
|
||||
|
||||
i = parse( buffer.toString() ).getDeclarations();
|
||||
IASTFunction foo1 = (IASTFunction)i.next();
|
||||
IASTFunction foo2 = (IASTFunction)i.next();
|
||||
assertTrue( foo1.takesVarArgs() );
|
||||
assertFalse( foo2.takesVarArgs() );
|
||||
assertAllReferences( 1, createTaskList( new Task( foo2 ) ) );
|
||||
|
||||
buffer = new StringBuffer();
|
||||
buffer.append( "void foo( ... ) {}\n" );
|
||||
buffer.append( "void foo( int x = 1) {}\n" );
|
||||
buffer.append( "void main( ){ foo(); }\n" );
|
||||
|
||||
i = parse( buffer.toString() ).getDeclarations();
|
||||
foo1 = (IASTFunction)i.next();
|
||||
foo2 = (IASTFunction)i.next();
|
||||
assertTrue( foo1.takesVarArgs() );
|
||||
assertFalse( foo2.takesVarArgs() );
|
||||
assertAllReferences( 1, createTaskList( new Task( foo2 ) ) );
|
||||
|
||||
buffer = new StringBuffer();
|
||||
buffer.append( "void foo( int x ... ) {}\n" );
|
||||
buffer.append( "void main( ){ foo( 1, 2, 'a' ); }\n" );
|
||||
|
||||
i = parse( buffer.toString() ).getDeclarations();
|
||||
foo = (IASTFunction)i.next();
|
||||
assertTrue( foo.takesVarArgs() );
|
||||
assertAllReferences( 1, createTaskList( new Task( foo ) ) );
|
||||
}
|
||||
|
||||
public void testBug48307_FriendFunction_1() throws Exception {
|
||||
StringWriter writer = new StringWriter();
|
||||
writer.write( "class A{ public : void foo(); }; " );
|
||||
|
|
|
@ -3355,5 +3355,83 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
assertTrue( results.contains( a3_int ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* void foo( ... ){ }
|
||||
*
|
||||
* foo( 1 );
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testBug43110_Ellipses() throws Exception{
|
||||
newTable();
|
||||
|
||||
IParameterizedSymbol foo = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
|
||||
foo.setHasVariableArgs( true );
|
||||
|
||||
table.getCompilationUnit().addSymbol( foo );
|
||||
|
||||
List params = new LinkedList();
|
||||
|
||||
TypeInfo p1 = new TypeInfo( TypeInfo.t_int, 0, null );
|
||||
params.add( p1 );
|
||||
|
||||
ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
|
||||
|
||||
assertEquals( foo, look );
|
||||
}
|
||||
|
||||
/**
|
||||
* void foo( ... ) {}; //#1
|
||||
* void foo( int i ) {}; //#2
|
||||
*
|
||||
* foo( 1 ); // calls foo #2
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testBug43110_EllipsesRanking() throws Exception{
|
||||
newTable();
|
||||
|
||||
IParameterizedSymbol foo1 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
|
||||
foo1.setHasVariableArgs( true );
|
||||
|
||||
table.getCompilationUnit().addSymbol( foo1 );
|
||||
|
||||
IParameterizedSymbol foo2 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
|
||||
foo2.addParameter( TypeInfo.t_int, 0, null, false );
|
||||
table.getCompilationUnit().addSymbol( foo2 );
|
||||
|
||||
List params = new LinkedList();
|
||||
|
||||
TypeInfo p1 = new TypeInfo( TypeInfo.t_int, 0, null );
|
||||
params.add( p1 );
|
||||
|
||||
ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
|
||||
|
||||
assertEquals( foo2, look );
|
||||
}
|
||||
|
||||
/**
|
||||
* void foo( int i = 0 ) {}; //#1
|
||||
* void foo( ... ) {}; //#2
|
||||
*
|
||||
* foo(); //calls #1
|
||||
* @throws Exception
|
||||
*/
|
||||
public void testBug43110_ElipsesRanking_2() throws Exception{
|
||||
newTable();
|
||||
|
||||
IParameterizedSymbol foo1 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
|
||||
foo1.addParameter( TypeInfo.t_int, 0, null, true );
|
||||
table.getCompilationUnit().addSymbol( foo1 );
|
||||
|
||||
IParameterizedSymbol foo2 = table.newParameterizedSymbol( "foo", TypeInfo.t_function );
|
||||
foo2.setHasVariableArgs( true );
|
||||
table.getCompilationUnit().addSymbol( foo2 );
|
||||
|
||||
List params = new LinkedList();
|
||||
|
||||
ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "foo", params );
|
||||
|
||||
assertEquals( foo1, look );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -55,7 +55,7 @@ public class ASTFunction extends ASTScope implements IASTFunction
|
|||
* @param ownerTemplate
|
||||
* @param references
|
||||
*/
|
||||
public ASTFunction(IParameterizedSymbol symbol, int nameEndOffset, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, int startOffset, int nameOffset, IASTTemplate ownerTemplate, List references, boolean previouslyDeclared, boolean hasFunctionTryBlock, boolean hasVarArgs)
|
||||
public ASTFunction(IParameterizedSymbol symbol, int nameEndOffset, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, int startOffset, int nameOffset, IASTTemplate ownerTemplate, List references, boolean previouslyDeclared, boolean hasFunctionTryBlock )
|
||||
{
|
||||
super( symbol );
|
||||
this.parameters = parameters;
|
||||
|
@ -70,7 +70,6 @@ public class ASTFunction extends ASTScope implements IASTFunction
|
|||
qualifiedName = new ASTQualifiedNamedElement( getOwnerScope(), symbol.getName() );
|
||||
this.previouslyDeclared =previouslyDeclared;
|
||||
this.hasFunctionTryBlock = hasFunctionTryBlock;
|
||||
this.varArgs = hasVarArgs;
|
||||
}
|
||||
|
||||
|
||||
|
@ -306,7 +305,7 @@ public class ASTFunction extends ASTScope implements IASTFunction
|
|||
|
||||
|
||||
private boolean hasFunctionTryBlock = false;
|
||||
private final boolean varArgs;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.parser.ast.IASTFunction#setHasFunctionTryBlock(boolean)
|
||||
*/
|
||||
|
@ -337,6 +336,6 @@ public class ASTFunction extends ASTScope implements IASTFunction
|
|||
* @see org.eclipse.cdt.core.parser.ast.IASTFunction#takesVarArgs()
|
||||
*/
|
||||
public boolean takesVarArgs() {
|
||||
return varArgs;
|
||||
return ((IParameterizedSymbol)getSymbol()).hasVariableArgs();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public class ASTMethod extends ASTFunction implements IASTMethod
|
|||
* @param references
|
||||
*/
|
||||
public ASTMethod(IParameterizedSymbol symbol, int nameEndOffset, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, int startOffset, int nameOffset, IASTTemplate ownerTemplate, List references, boolean previouslyDeclared,
|
||||
boolean isConstructor, boolean isDestructor, boolean isPureVirtual, ASTAccessVisibility visibility, List constructorChain, boolean hasFunctionTryBlock, boolean hasVariableArguments )
|
||||
boolean isConstructor, boolean isDestructor, boolean isPureVirtual, ASTAccessVisibility visibility, List constructorChain, boolean hasFunctionTryBlock )
|
||||
{
|
||||
super(
|
||||
symbol,
|
||||
|
@ -57,7 +57,7 @@ public class ASTMethod extends ASTFunction implements IASTMethod
|
|||
startOffset,
|
||||
nameOffset,
|
||||
ownerTemplate,
|
||||
references, previouslyDeclared, hasFunctionTryBlock, hasVariableArguments );
|
||||
references, previouslyDeclared, hasFunctionTryBlock );
|
||||
this.visibility = visibility;
|
||||
this.isConstructor = isConstructor;
|
||||
this.isDestructor = isDestructor;
|
||||
|
|
|
@ -1654,6 +1654,8 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
|||
IParameterizedSymbol symbol = pst.newParameterizedSymbol( name.getLastToken().getImage(), TypeInfo.t_function );
|
||||
setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol);
|
||||
|
||||
symbol.setHasVariableArgs( hasVariableArguments );
|
||||
|
||||
setParameter( symbol, returnType, false, references );
|
||||
setParameters( symbol, references, parameters.iterator() );
|
||||
|
||||
|
@ -1690,7 +1692,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
|||
{
|
||||
throw new ASTSemanticException();
|
||||
}
|
||||
ASTFunction function = new ASTFunction( symbol, nameEndOffset, parameters, returnType, exception, startOffset, nameOffset, ownerTemplate, references, previouslyDeclared, hasFunctionTryBlock, hasVariableArguments );
|
||||
ASTFunction function = new ASTFunction( symbol, nameEndOffset, parameters, returnType, exception, startOffset, nameOffset, ownerTemplate, references, previouslyDeclared, hasFunctionTryBlock );
|
||||
try
|
||||
{
|
||||
attachSymbolExtension(symbol, function);
|
||||
|
@ -1935,6 +1937,8 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
|||
IParameterizedSymbol symbol = pst.newParameterizedSymbol( nameDuple.toString(), TypeInfo.t_function );
|
||||
setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol);
|
||||
setMethodTypeInfoBits( symbol, isConst, isVolatile, isVirtual, isExplicit );
|
||||
symbol.setHasVariableArgs( hasVariableArguments );
|
||||
|
||||
if(references == null)
|
||||
references = new ArrayList();
|
||||
|
||||
|
@ -2027,7 +2031,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
|
|||
|
||||
resolveLeftoverConstructorInitializerMembers( symbol, constructorChain );
|
||||
|
||||
ASTMethod method = new ASTMethod( symbol, nameEndOffset, parameters, returnType, exception, startOffset, nameOffset, ownerTemplate, references, previouslyDeclared, isConstructor, isDestructor, isPureVirtual, visibility, constructorChain, hasFunctionTryBlock, hasVariableArguments );
|
||||
ASTMethod method = new ASTMethod( symbol, nameEndOffset, parameters, returnType, exception, startOffset, nameOffset, ownerTemplate, references, previouslyDeclared, isConstructor, isDestructor, isPureVirtual, visibility, constructorChain, hasFunctionTryBlock );
|
||||
try
|
||||
{
|
||||
attachSymbolExtension( symbol, method );
|
||||
|
|
|
@ -45,6 +45,9 @@ public interface IParameterizedSymbol extends IContainerSymbol {
|
|||
public void setReturnType( ISymbol type );
|
||||
public ISymbol getReturnType();
|
||||
|
||||
public void setHasVariableArgs( boolean var );
|
||||
public boolean hasVariableArgs( );
|
||||
|
||||
public boolean hasSpecializations();
|
||||
public void addSpecialization( IParameterizedSymbol spec );
|
||||
public List getSpecializations();
|
||||
|
|
|
@ -240,6 +240,13 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz
|
|||
return _specializations;
|
||||
}
|
||||
|
||||
public void setHasVariableArgs( boolean var ){
|
||||
_hasVarArgs = var;
|
||||
}
|
||||
|
||||
public boolean hasVariableArgs( ){
|
||||
return _hasVarArgs;
|
||||
}
|
||||
|
||||
static private class AddParameterCommand extends Command{
|
||||
public AddParameterCommand( IParameterizedSymbol container, ISymbol parameter ){
|
||||
|
@ -279,4 +286,5 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz
|
|||
private LinkedList _specializations; //template specializations
|
||||
private LinkedList _argumentList; //template specialization arguments
|
||||
private ISymbol _returnType;
|
||||
private boolean _hasVarArgs = false; //whether or not this function has variable arguments
|
||||
}
|
||||
|
|
|
@ -850,10 +850,10 @@ public class ParserSymbolTable {
|
|||
}
|
||||
}
|
||||
}
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
|
||||
}else{
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
|
||||
}
|
||||
|
||||
if( data.parameters == null )
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
|
||||
}
|
||||
|
||||
IParameterizedSymbol bestFn = null; //the best function
|
||||
|
@ -866,7 +866,6 @@ public class ParserSymbolTable {
|
|||
Iterator targetParams = null;
|
||||
|
||||
int numTargetParams = 0;
|
||||
int numParams = 0;
|
||||
int comparison;
|
||||
Cost cost = null;
|
||||
Cost temp = null;
|
||||
|
@ -880,6 +879,16 @@ public class ParserSymbolTable {
|
|||
boolean currHasAmbiguousParam = false;
|
||||
boolean bestHasAmbiguousParam = false;
|
||||
|
||||
List parameters = null;
|
||||
|
||||
if( numSourceParams == 0 ){
|
||||
parameters = new LinkedList();
|
||||
parameters.add( new TypeInfo( TypeInfo.t_void, 0, null ) );
|
||||
numSourceParams = 1;
|
||||
} else {
|
||||
parameters = data.parameters;
|
||||
}
|
||||
|
||||
for( int i = numFns; i > 0; i-- ){
|
||||
currFn = (IParameterizedSymbol) iterFns.next();
|
||||
|
||||
|
@ -892,15 +901,14 @@ public class ParserSymbolTable {
|
|||
}
|
||||
}
|
||||
|
||||
sourceParams = data.parameters.iterator();
|
||||
sourceParams = parameters.iterator();
|
||||
|
||||
List parameterList = null;
|
||||
if( currFn.getParameterList().isEmpty() ){
|
||||
if( currFn.getParameterList().isEmpty() && !currFn.hasVariableArgs() ){
|
||||
//the only way we get here and have no parameters, is if we are looking
|
||||
//for a function that takes void parameters ie f( void )
|
||||
parameterList = new LinkedList();
|
||||
parameterList.add( currFn.getSymbolTable().newSymbol( "", TypeInfo.t_void ) );
|
||||
targetParams = parameterList.iterator();
|
||||
} else {
|
||||
parameterList = currFn.getParameterList();
|
||||
}
|
||||
|
@ -908,24 +916,33 @@ public class ParserSymbolTable {
|
|||
targetParams = parameterList.iterator();
|
||||
numTargetParams = parameterList.size();
|
||||
|
||||
//we only need to look at the smaller number of parameters
|
||||
//(a larger number in the Target means default parameters, a larger
|
||||
//number in the source means ellipses.)
|
||||
numParams = ( numTargetParams < numSourceParams ) ? numTargetParams : numSourceParams;
|
||||
|
||||
if( currFnCost == null ){
|
||||
currFnCost = new Cost [ numParams ];
|
||||
currFnCost = new Cost [ numSourceParams ];
|
||||
}
|
||||
|
||||
comparison = 0;
|
||||
boolean varArgs = false;
|
||||
|
||||
for( int j = 0; j < numParams; j++ ){
|
||||
for( int j = 0; j < numSourceParams; j++ ){
|
||||
source = (TypeInfo) sourceParams.next();
|
||||
target = ((ISymbol)targetParams.next()).getTypeInfo();
|
||||
if( source.equals( target ) ){
|
||||
|
||||
if( targetParams.hasNext() )
|
||||
target = ((ISymbol)targetParams.next()).getTypeInfo();
|
||||
else
|
||||
varArgs = true;
|
||||
|
||||
if( varArgs ){
|
||||
cost = new Cost( source, null );
|
||||
cost.rank = Cost.ELLIPSIS_CONVERSION;
|
||||
} else if ( target.getHasDefault() && source.isType( TypeInfo.t_void ) && !source.hasPtrOperators() ){
|
||||
//source is just void, ie no parameter, if target had a default, then use that
|
||||
cost = new Cost( source, target );
|
||||
cost.rank = Cost.IDENTITY_RANK;
|
||||
} else if( source.equals( target ) ){
|
||||
cost = new Cost( source, target );
|
||||
cost.rank = Cost.IDENTITY_RANK; //exact match, no cost
|
||||
} else {
|
||||
|
||||
cost = checkStandardConversionSequence( source, target );
|
||||
|
||||
//12.3-4 At most one user-defined conversion is implicitly applied to
|
||||
|
@ -947,7 +964,7 @@ public class ParserSymbolTable {
|
|||
//In order for this function to be better than the previous best, it must
|
||||
//have at least one parameter match that is better that the corresponding
|
||||
//match for the other function, and none that are worse.
|
||||
for( int j = 0; j < numParams; j++ ){
|
||||
for( int j = 0; j < numSourceParams; j++ ){
|
||||
if( currFnCost[ j ].rank < 0 ){
|
||||
hasWorse = true;
|
||||
hasBetter = false;
|
||||
|
@ -1021,10 +1038,13 @@ public class ParserSymbolTable {
|
|||
|
||||
//A candidate function having fewer than m parameters is viable only if it has an
|
||||
//ellipsis in its parameter list.
|
||||
if( num < numParameters ) {
|
||||
//TODO ellipsis
|
||||
//not enough parameters, remove it
|
||||
iter.remove();
|
||||
if( num < numParameters ){
|
||||
if( function.hasVariableArgs() ) {
|
||||
continue;
|
||||
} else {
|
||||
//not enough parameters, remove it
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
//a candidate function having more than m parameters is viable only if the (m+1)-st
|
||||
//parameter has a default argument
|
||||
|
@ -2287,8 +2307,8 @@ public class ParserSymbolTable {
|
|||
{
|
||||
|
||||
public Cost( TypeInfo s, TypeInfo t ){
|
||||
source = new TypeInfo( s );
|
||||
target = new TypeInfo( t );
|
||||
source = ( s != null ) ? new TypeInfo( s ) : new TypeInfo();
|
||||
target = ( t != null ) ? new TypeInfo( t ) : new TypeInfo();
|
||||
}
|
||||
|
||||
public TypeInfo source;
|
||||
|
|
Loading…
Add table
Reference in a new issue