1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

address of overloaded functions

This commit is contained in:
Andrew Niefer 2005-02-18 02:46:14 +00:00
parent 2b3b0671c9
commit 47cc24fc13
4 changed files with 374 additions and 34 deletions

View file

@ -1795,5 +1795,94 @@ public class AST2CPPTests extends AST2BaseTest {
assertEquals( friends.length, 1 );
assertSame( friends[0], helper );
}
public void testBug45763_1() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append( "void f( int ); \n"); //$NON-NLS-1$
buffer.append( "void f( char ); \n"); //$NON-NLS-1$
buffer.append( "void (*pf) (int) = &f; \n"); //$NON-NLS-1$
buffer.append( "void foo() { \n"); //$NON-NLS-1$
buffer.append( " pf = &f; \n"); //$NON-NLS-1$
buffer.append( "} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
CPPVisitor.visitTranslationUnit(tu, col);
IFunction f1 = (IFunction) col.getName(0).resolveBinding();
IFunction f2 = (IFunction) col.getName(2).resolveBinding();
IVariable pf = (IVariable) col.getName(4).resolveBinding();
assertInstances( col, pf, 2 );
assertInstances( col, f1, 3 );
assertInstances( col, f2, 1 );
}
public void testBug45763_2() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append( "void f( char ); \n"); //$NON-NLS-1$
buffer.append( "void f( int ); \n"); //$NON-NLS-1$
buffer.append( "void g( void (*)( int ) ) {} \n"); //$NON-NLS-1$
buffer.append( "void (*pg)( void(*)(int) ); \n"); //$NON-NLS-1$
buffer.append( "void foo() { \n"); //$NON-NLS-1$
buffer.append( " g( &f ); \n"); //$NON-NLS-1$
buffer.append( " (*pg)( &f ); \n"); //$NON-NLS-1$
buffer.append( "} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
CPPVisitor.visitTranslationUnit(tu, col);
IFunction f1 = (IFunction) col.getName(0).resolveBinding();
IFunction f2 = (IFunction) col.getName(2).resolveBinding();
IFunction g = (IFunction) col.getName(4).resolveBinding();
IVariable pg = (IVariable) col.getName(7).resolveBinding();
assertInstances( col, f1, 1 );
assertInstances( col, f2, 3 );
assertInstances( col, g, 2 );
assertInstances( col, pg, 2 );
}
public void testBug45763_3() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("void f( int ); \n"); //$NON-NLS-1$
buffer.append("void f( char ); \n"); //$NON-NLS-1$
buffer.append("void (* bar () ) ( int ) { \n"); //$NON-NLS-1$
buffer.append(" return &f; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
CPPVisitor.visitTranslationUnit(tu, col);
IFunction f1 = (IFunction) col.getName(0).resolveBinding();
IFunction f2 = (IFunction) col.getName(2).resolveBinding();
IFunction bar = (IFunction) col.getName(4).resolveBinding();
assertNotNull( bar );
assertInstances( col, f1, 2 );
assertInstances( col, f2, 1 );
}
public void _testBug45763_4() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("void f( int ); \n"); //$NON-NLS-1$
buffer.append("void f( char ); \n"); //$NON-NLS-1$
buffer.append("void foo () { \n"); //$NON-NLS-1$
buffer.append(" ( void (*)(int) ) &f; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
CPPNameCollector col = new CPPNameCollector();
CPPVisitor.visitTranslationUnit(tu, col);
IFunction f1 = (IFunction) col.getName(0).resolveBinding();
IFunction f2 = (IFunction) col.getName(2).resolveBinding();
IFunction bar = (IFunction) col.getName(4).resolveBinding();
assertNotNull( bar );
assertInstances( col, f1, 2 );
assertInstances( col, f2, 1 );
}
}

View file

@ -14,6 +14,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -157,10 +158,16 @@ public class CPPFunction implements IFunction, ICPPBinding {
public IScope getScope() {
ICPPASTDeclSpecifier declSpec = null;
if( definition != null ){
IASTFunctionDefinition def = (IASTFunctionDefinition) definition.getParent();
IASTNode node = definition.getParent();
while( node instanceof IASTDeclarator )
node = node.getParent();
IASTFunctionDefinition def = (IASTFunctionDefinition) node;
declSpec = (ICPPASTDeclSpecifier) def.getDeclSpecifier();
} else {
IASTSimpleDeclaration decl = (IASTSimpleDeclaration) declarations[0].getParent();
IASTNode node = declarations[0].getParent();
while( node instanceof IASTDeclarator )
node = node.getParent();
IASTSimpleDeclaration decl = (IASTSimpleDeclaration)node;
declSpec = (ICPPASTDeclSpecifier) decl.getDeclSpecifier();
}

View file

@ -15,6 +15,8 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
@ -31,15 +33,18 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
@ -53,6 +58,7 @@ import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.c.ICASTFieldDesignator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
@ -116,6 +122,7 @@ public class CPPSemantics {
public Object [] functionParameters;
public boolean forUserDefinedConversion;
public ProblemBinding problem;
public boolean forAssociatedScopes = false;
public LookupData( IASTName n ){
astName = n;
@ -341,12 +348,13 @@ public class CPPSemantics {
return result;
}
}
static protected IBinding resolveBinding( IASTName name ){
// if( name instanceof ICPPASTQualifiedName && ((ICPPASTQualifiedName)name).isFullyQualified() )
// return ((ICPPASTTranslationUnit)name.getTranslationUnit()).resolveBinding();
//1: get some context info off of the name to figure out what kind of lookup we want
LookupData data = createLookupData( name );
LookupData data = createLookupData( name, true );
try {
//2: lookup
@ -422,11 +430,13 @@ public class CPPSemantics {
return binding;
}
static private CPPSemantics.LookupData createLookupData( IASTName name ){
static private CPPSemantics.LookupData createLookupData( IASTName name, boolean considerAssociatedScopes ){
CPPSemantics.LookupData data = new CPPSemantics.LookupData( name );
IASTNode parent = name.getParent();
if( parent instanceof ICPPASTQualifiedName ){
parent = parent.getParent();
}
if( parent instanceof ICPPASTFunctionDeclarator ){
data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters();
} else if( parent instanceof IASTIdExpression ){
@ -440,20 +450,6 @@ public class CPPSemantics {
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
}
}
} else if( parent instanceof ICPPASTFunctionDeclarator ){
data.functionParameters = ((ICPPASTFunctionDeclarator)parent).getParameters();
} else if( parent instanceof IASTIdExpression ){
parent = parent.getParent();
if( parent instanceof IASTFunctionCallExpression ){
IASTExpression exp = ((IASTFunctionCallExpression)parent).getParameterExpression();
if( exp instanceof IASTExpressionList )
data.functionParameters = ((IASTExpressionList) exp ).getExpressions();
else if( exp != null )
data.functionParameters = new IASTExpression [] { exp };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
}
} else if( parent instanceof ICPPASTFieldReference && parent.getParent() instanceof IASTFunctionCallExpression ){
IASTExpression exp = ((IASTFunctionCallExpression)parent.getParent()).getParameterExpression();
if( exp instanceof IASTExpressionList )
@ -464,13 +460,19 @@ public class CPPSemantics {
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
} else if( parent instanceof ICPPASTNamedTypeSpecifier && parent.getParent() instanceof IASTTypeId ){
IASTTypeId typeId = (IASTTypeId) parent.getParent();
if( typeId.getAbstractDeclarator() instanceof IASTFunctionDeclarator ){
ICPPASTFunctionDeclarator fdtor = (ICPPASTFunctionDeclarator) typeId.getAbstractDeclarator();
data.functionParameters = fdtor.getParameters();
if( typeId.getParent() instanceof ICPPASTNewExpression ){
ICPPASTNewExpression newExp = (ICPPASTNewExpression) typeId.getParent();
IASTExpression init = newExp.getNewInitializer();
if( init instanceof IASTExpressionList )
data.functionParameters = ((IASTExpressionList) init ).getExpressions();
else if( init != null )
data.functionParameters = new IASTExpression [] { init };
else
data.functionParameters = IASTExpression.EMPTY_EXPRESSION_ARRAY;
}
}
if( !(name.getParent() instanceof ICPPASTQualifiedName) && data.functionCall() ){
if( considerAssociatedScopes && !(name.getParent() instanceof ICPPASTQualifiedName) && data.functionCall() ){
data.associated = getAssociatedScopes( data );
}
@ -1045,7 +1047,7 @@ public class CPPSemantics {
else if( bindings.length == 1 )
return bindings[ 0 ];
LookupData data = createLookupData( name );
LookupData data = createLookupData( name, false );
data.foundItems = bindings;
try {
return resolveAmbiguities( data, name );
@ -1246,6 +1248,11 @@ public class CPPSemantics {
return fns[ 0 ];
return new CPPCompositeBinding( fns );
}
//we don't have any arguments with which to resolve the function
if( data.functionParameters == null ){
return resolveTargetedFunction( data, fns );
}
//reduce our set of candidate functions to only those who have the right number of parameters
reduceToViable( data, fns );
@ -1402,6 +1409,220 @@ public class CPPSemantics {
return bestFn;
}
/**
* 13.4-1 A use of an overloaded function without arguments is resolved in certain contexts to a function
* @param data
* @param fns
* @return
*/
private static IBinding resolveTargetedFunction( LookupData data, IBinding[] fns ) {
if( fns.length == 1 )
return fns[0];
if( data.forAssociatedScopes ){
return new CPPCompositeBinding( fns );
}
IBinding result = null;
Object o = getTargetType( data );
IType type, types[] = null;
int idx = -1;
if( o instanceof IType [] ){
types = (IType[]) o;
type = types[ ++idx ];
} else
type = (IType) o;
while( type != null ){
type = (type != null) ? getUltimateType( type, false ) : null;
if( type == null || !( type instanceof IFunctionType ) )
return new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
for( int i = 0; i < fns.length; i++ ){
IFunction fn = (IFunction) fns[i];
IType ft = null;
try {
ft = fn.getType();
} catch ( DOMException e ) {
ft = e.getProblem();
}
if( type.equals( ft ) ){
if( result == null )
result = fn;
else
return new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
}
}
if( idx > 0 && ++idx < types.length ){
type = types[idx];
} else {
type = null;
}
}
return ( result != null ) ? result : new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
}
private static Object getTargetType( LookupData data ){
IASTName name = data.astName;
if( name.getPropertyInParent() == ICPPASTQualifiedName.SEGMENT_NAME )
name = (IASTName) name.getParent();
if( name.getPropertyInParent() != IASTIdExpression.ID_NAME )
return null;
IASTIdExpression idExp = (IASTIdExpression) name.getParent();
IASTNode node = idExp.getParent();
ASTNodeProperty prop = null;
while( node != null ){
prop = node.getPropertyInParent();
//target is an object or reference being initialized
if( prop == IASTInitializerExpression.INITIALIZER_EXPRESSION ){
IASTInitializerExpression initExp = (IASTInitializerExpression) node.getParent();
IASTDeclarator dtor = (IASTDeclarator) initExp.getParent();
return CPPVisitor.createType( dtor );
}
//target is the left side of an assignment
else if( prop == IASTBinaryExpression.OPERAND_TWO &&
((IASTBinaryExpression)node.getParent()).getOperator() == IASTBinaryExpression.op_assign )
{
IASTBinaryExpression binaryExp = (IASTBinaryExpression) node.getParent();
IASTExpression exp = binaryExp.getOperand1();
return CPPVisitor.getExpressionType( exp );
}
//target is a parameter of a function
else if( prop == IASTFunctionCallExpression.PARAMETERS ||
(prop == IASTExpressionList.NESTED_EXPRESSION && node.getParent().getPropertyInParent() == IASTFunctionCallExpression.PARAMETERS ) )
{
//if this function call refers to an overloaded function, there is more than one possiblity
//for the target type
IASTFunctionCallExpression fnCall = null;
int idx = -1;
if( prop == IASTFunctionCallExpression.PARAMETERS ){
fnCall = (IASTFunctionCallExpression) node.getParent();
idx = 0;
} else {
IASTExpressionList list = (IASTExpressionList) node.getParent();
fnCall = (IASTFunctionCallExpression) list.getParent();
IASTExpression [] exps = list.getExpressions();
for( int i = 0; i < exps.length; i++ ){
if( exps[i] == node ){
idx = i;
break;
}
}
}
IFunctionType [] types = getPossibleFunctions( fnCall );
if( types == null ) return null;
IType [] result = null;
for( int i = 0; i < types.length && types[i] != null; i++ ){
IType [] pts = null;
try {
pts = types[i].getParameterTypes();
} catch ( DOMException e ) {
continue;
}
if( pts.length > idx )
result = (IType[]) ArrayUtil.append( IType.class, result, pts[idx] );
}
return result;
}
//target is an explicit type conversion
// else if( prop == ICPPASTSimpleTypeConstructorExpression.INITIALIZER_VALUE )
// {
//
// }
//target is an explicit type conversion
else if( prop == IASTCastExpression.OPERAND )
{
IASTCastExpression cast = (IASTCastExpression) node.getParent();
return CPPVisitor.createType( cast.getTypeId().getAbstractDeclarator() );
}
//target is the return value of a function, operator or conversion
else if( prop == IASTReturnStatement.RETURNVALUE )
{
while( !( node instanceof IASTFunctionDefinition ) ){
node = node.getParent();
}
IASTDeclarator dtor = ((IASTFunctionDefinition)node).getDeclarator();
while( dtor.getNestedDeclarator() != null )
dtor = dtor.getNestedDeclarator();
IBinding binding = dtor.getName().resolveBinding();
if( binding instanceof IFunction ){
try {
IFunctionType ft = ((IFunction)binding).getType();
return ft.getReturnType();
} catch ( DOMException e ) {
}
}
}
else if( prop == IASTUnaryExpression.OPERAND ){
IASTUnaryExpression parent = (IASTUnaryExpression) node.getParent();
if( parent.getOperator() == IASTUnaryExpression.op_bracketedPrimary ||
parent.getOperator() == IASTUnaryExpression.op_amper)
{
node = parent;
continue;
}
}
break;
}
return null;
}
static private IFunctionType [] getPossibleFunctions( IASTFunctionCallExpression call ){
IFunctionType [] result = null;
IASTExpression exp = call.getFunctionNameExpression();
if( exp instanceof IASTIdExpression ){
IASTIdExpression idExp = (IASTIdExpression) exp;
IASTName name = idExp.getName();
LookupData data = createLookupData( name, false );
try {
lookup( data, name );
} catch ( DOMException e1 ) {
return null;
}
if( data.foundItems != null && data.foundItems.length > 0 ){
IBinding temp = null;
for( int i = 0; i < data.foundItems.length; i++ ){
Object o = data.foundItems[i];
if( o == null ) break;
if( o instanceof IASTName )
temp = ((IASTName) o).resolveBinding();
else if( o instanceof IBinding ){
temp = (IBinding) o;
if( !declaredBefore( temp, name ) )
continue;
} else
continue;
try {
if( temp instanceof IFunction ){
result = (IFunctionType[]) ArrayUtil.append( IFunctionType.class, result, ((IFunction)temp).getType() );
} else if( temp instanceof IVariable ){
IType type = getUltimateType( ((IVariable) temp).getType(), false );
if( type instanceof IFunctionType )
result = (IFunctionType[]) ArrayUtil.append( IFunctionType.class, result, type );
}
} catch( DOMException e ){
}
}
}
} else {
IType type = CPPVisitor.getExpressionType( exp );
type = getUltimateType( type, false );
if( type instanceof IFunctionType ){
result = new IFunctionType[] { (IFunctionType) type };
}
}
return result;
}
static private Cost checkStandardConversionSequence( IType source, IType target ) throws DOMException {
Cost cost = lvalue_to_rvalue( source, target );

View file

@ -425,6 +425,8 @@ public class CPPVisitor {
} else if( parent instanceof IASTParameterDeclaration ){
IASTParameterDeclaration param = (IASTParameterDeclaration) parent;
IASTStandardFunctionDeclarator fDtor = (IASTStandardFunctionDeclarator) param.getParent();
if( fDtor.getParent() instanceof IASTDeclarator || fDtor.getNestedDeclarator() != null )
return null;
IBinding temp = fDtor.getName().resolveBinding();
if( temp instanceof IFunction ){
CPPFunction function = (CPPFunction) temp;
@ -582,12 +584,13 @@ public class CPPVisitor {
} else if( parent instanceof IASTFunctionDefinition ){
IASTFunctionDeclarator fnDeclarator = ((IASTFunctionDefinition) parent ).getDeclarator();
IFunction function = (IFunction) fnDeclarator.getName().resolveBinding();
if( function != null ){
try {
scope = function.getScope();
} catch ( DOMException e ) {
}
}
}
if( statement instanceof IASTGotoStatement || statement instanceof IASTLabelStatement ){
while( !(parent instanceof IASTFunctionDefinition) ){
@ -626,20 +629,33 @@ public class CPPVisitor {
}
static private IBinding resolveBinding( IASTNode node ){
IASTName name = null;
while( node != null ) {
if( node instanceof IASTIdExpression ){
return CPPSemantics.resolveBinding( ((IASTIdExpression)node).getName() );
name = ((IASTIdExpression) node).getName();
break;
//return CPPSemantics.resolveBinding( ((IASTIdExpression)node).getName() );
} else if( node instanceof ICPPASTFieldReference ){
return CPPSemantics.resolveBinding( ((ICPPASTFieldReference)node).getFieldName() );
name = ((ICPPASTFieldReference)node).getFieldName();
break;
} else if( node instanceof IASTFunctionCallExpression ){
node = ((IASTFunctionCallExpression)node).getFunctionNameExpression();
} else if( node instanceof IASTUnaryExpression ){
node = ((IASTUnaryExpression)node).getOperand();
} else if( node instanceof IASTBinaryExpression ){
node = ((IASTBinaryExpression)node).getOperand2();
} else
node = null;
}
if( name != null ){
IBinding binding = CPPSemantics.resolveBinding( name );
if( name instanceof ICPPASTQualifiedName ){
IASTName ns [] = ((ICPPASTQualifiedName)name).getNames();
name = ns[ ns.length - 1 ];
}
((CPPASTName)name).setBinding( binding );
return binding;
}
return null;
}
@ -1684,6 +1700,7 @@ public class CPPVisitor {
}
return type;
}
/**
* @param expression
* @return
@ -1701,6 +1718,12 @@ public class CPPVisitor {
}
} else if( binding instanceof IProblemBinding ){
return (IType) binding;
} else if( binding instanceof IFunction ){
try {
return ((IFunction)binding).getType();
} catch ( DOMException e ){
return e.getProblem();
}
}
} else if( expression instanceof IASTCastExpression ){
IASTTypeId id = ((IASTCastExpression)expression).getTypeId();