1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-28 11:25:35 +02:00

- fix up how we resolve function parameter bindings in C

This commit is contained in:
Andrew Niefer 2005-01-25 22:16:03 +00:00
parent ae4dff5290
commit 0a1793e33f
5 changed files with 212 additions and 151 deletions

View file

@ -46,7 +46,7 @@ import org.eclipse.cdt.core.dom.ast.c.ICBasicType;
import org.eclipse.cdt.core.dom.ast.c.ICScope; import org.eclipse.cdt.core.dom.ast.c.ICScope;
import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.c.CKnRParameter; import org.eclipse.cdt.internal.core.dom.parser.c.CParameter;
import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor;
import org.eclipse.cdt.internal.core.dom.parser.c.ICBinding; import org.eclipse.cdt.internal.core.dom.parser.c.ICBinding;
@ -215,6 +215,7 @@ public class AST2KnRTests extends AST2BaseTest {
IASTSimpleDeclaration isroot_decl = (IASTSimpleDeclaration)tu.getDeclarations()[1]; IASTSimpleDeclaration isroot_decl = (IASTSimpleDeclaration)tu.getDeclarations()[1];
IASTFunctionDefinition isroot_def = (IASTFunctionDefinition)tu.getDeclarations()[2]; IASTFunctionDefinition isroot_def = (IASTFunctionDefinition)tu.getDeclarations()[2];
IASTName x0 = ((IASTStandardFunctionDeclarator)isroot_decl.getDeclarators()[0]).getParameters()[0].getDeclarator().getName();
IASTName x1 = ((ICASTKnRFunctionDeclarator)isroot_def.getDeclarator()).getParameterNames()[0]; IASTName x1 = ((ICASTKnRFunctionDeclarator)isroot_def.getDeclarator()).getParameterNames()[0];
IASTName x2 = ((IASTSimpleDeclaration)((ICASTKnRFunctionDeclarator)isroot_def.getDeclarator()).getParameterDeclarations()[0]).getDeclarators()[0].getName(); IASTName x2 = ((IASTSimpleDeclaration)((ICASTKnRFunctionDeclarator)isroot_def.getDeclarator()).getParameterDeclarations()[0]).getDeclarators()[0].getName();
IASTName x3 = ((IASTIdExpression)((IASTBinaryExpression)((IASTReturnStatement)((IASTCompoundStatement)isroot_def.getBody()).getStatements()[0]).getReturnValue()).getOperand1()).getName(); IASTName x3 = ((IASTIdExpression)((IASTBinaryExpression)((IASTReturnStatement)((IASTCompoundStatement)isroot_def.getBody()).getStatements()[0]).getReturnValue()).getOperand1()).getName();
@ -247,8 +248,9 @@ public class AST2KnRTests extends AST2BaseTest {
// test tu.getDeclarations(IBinding) // test tu.getDeclarations(IBinding)
IASTName[] decls = tu.getDeclarations(x3.resolveBinding()); IASTName[] decls = tu.getDeclarations(x3.resolveBinding());
assertEquals( decls.length, 1 ); assertEquals( decls.length, 2 );
assertEquals( decls[0], x2 ); assertEquals( decls[0], x0 );
assertEquals( decls[1], x2 );
assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("c").toCharArray()) ); //$NON-NLS-1$ assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("c").toCharArray()) ); //$NON-NLS-1$
assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("isroot").toCharArray()) ); //$NON-NLS-1$ assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("isroot").toCharArray()) ); //$NON-NLS-1$
@ -484,6 +486,7 @@ public class AST2KnRTests extends AST2BaseTest {
IFunction f_fun1 = (IFunction)f_name1.resolveBinding(); IFunction f_fun1 = (IFunction)f_name1.resolveBinding();
assertEquals( f_name1.toString(), "f" ); //$NON-NLS-1$ assertEquals( f_name1.toString(), "f" ); //$NON-NLS-1$
assertEquals( f_decltor1.getParameters().length, 1 ); assertEquals( f_decltor1.getParameters().length, 1 );
IASTName x0 = f_decltor1.getParameters()[0].getDeclarator().getName();
IASTName A_name2 = ((ICASTTypedefNameSpecifier)f_decltor1.getParameters()[0].getDeclSpecifier()).getName(); IASTName A_name2 = ((ICASTTypedefNameSpecifier)f_decltor1.getParameters()[0].getDeclSpecifier()).getName();
assertEquals( A_name2.toString(), "A" ); //$NON-NLS-1$ assertEquals( A_name2.toString(), "A" ); //$NON-NLS-1$
ITypedef A_var2 = (ITypedef)A_name2.resolveBinding(); ITypedef A_var2 = (ITypedef)A_name2.resolveBinding();
@ -537,8 +540,9 @@ public class AST2KnRTests extends AST2BaseTest {
// test tu.getDeclarations(IBinding) // test tu.getDeclarations(IBinding)
IASTName[] decls = tu.getDeclarations(x2.resolveBinding()); IASTName[] decls = tu.getDeclarations(x2.resolveBinding());
assertEquals( decls.length, 1 ); assertEquals( decls.length, 2 );
assertEquals( decls[0], x2 ); assertEquals( decls[0], x0 );
assertEquals( decls[1], x2 );
assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_TAG, new String("A_struct").toCharArray()) ); //$NON-NLS-1$ assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_TAG, new String("A_struct").toCharArray()) ); //$NON-NLS-1$
assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("A").toCharArray()) ); //$NON-NLS-1$ assertNotNull( ((ICScope)tu.getScope()).getBinding(ICScope.NAMESPACE_TYPE_OTHER, new String("A").toCharArray()) ); //$NON-NLS-1$
@ -603,8 +607,8 @@ public class AST2KnRTests extends AST2BaseTest {
IFunction f_fun = (IFunction)f_decltor.getName().resolveBinding(); IFunction f_fun = (IFunction)f_decltor.getName().resolveBinding();
IParameter [] f_parms = f_fun.getParameters(); IParameter [] f_parms = f_fun.getParameters();
assertEquals( f_parms.length, 2 ); assertEquals( f_parms.length, 2 );
assertEquals( ((CKnRParameter)f_parms[0]).getName(), "a" ); //$NON-NLS-1$ assertEquals( ((CParameter)f_parms[0]).getName(), "a" ); //$NON-NLS-1$
assertEquals( ((CKnRParameter)f_parms[1]).getName(), "b" ); //$NON-NLS-1$ assertEquals( ((CParameter)f_parms[1]).getName(), "b" ); //$NON-NLS-1$
} }

View file

@ -1617,9 +1617,7 @@ public class AST2Tests extends AST2BaseTest {
assertEquals( decls.length, 1 ); assertEquals( decls.length, 1 );
assertEquals( decls[0], name_A1 ); assertEquals( decls[0], name_A1 );
decls = tu.getDeclarations(name_d.resolveBinding()); assertNull(name_d.resolveBinding());
assertEquals( decls.length, 1 );
assertEquals( decls[0], name_d );
} }
public void testDesignatedInitializers() throws ParserException public void testDesignatedInitializers() throws ParserException

View file

@ -19,6 +19,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IParameter;
@ -32,15 +33,15 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
* @author aniefer * @author aniefer
*/ */
public class CFunction implements IFunction, ICBinding { public class CFunction implements IFunction, ICBinding {
private IASTFunctionDeclarator [] declarators = null; private IASTStandardFunctionDeclarator [] declarators = null;
private IASTFunctionDeclarator definition; private IASTFunctionDeclarator definition;
IFunctionType type = null; IFunctionType type = null;
public CFunction( IASTFunctionDeclarator declarator ){ public CFunction( IASTFunctionDeclarator declarator ){
if( declarator.getParent() instanceof IASTFunctionDefinition ) if( declarator.getParent() instanceof IASTFunctionDefinition || declarator instanceof ICASTKnRFunctionDeclarator )
definition = declarator; definition = declarator;
else { else {
declarators = new IASTFunctionDeclarator [] { declarator }; declarators = new IASTStandardFunctionDeclarator [] { (IASTStandardFunctionDeclarator) declarator };
} }
} }
@ -48,36 +49,26 @@ public class CFunction implements IFunction, ICBinding {
return ( definition != null ) ? definition : declarators[0]; return ( definition != null ) ? definition : declarators[0];
} }
public void addDeclarator( IASTFunctionDeclarator fnDeclarator ){ public void addDeclarator( IASTFunctionDeclarator fnDeclarator ){
if( fnDeclarator instanceof IASTFunctionDefinition || fnDeclarator instanceof ICASTKnRFunctionDeclarator ) updateParameterBindings( fnDeclarator );
if( fnDeclarator.getParent() instanceof IASTFunctionDefinition || fnDeclarator instanceof ICASTKnRFunctionDeclarator )
definition = fnDeclarator; definition = fnDeclarator;
else { else {
if( declarators == null ){ if( declarators == null ){
declarators = new IASTFunctionDeclarator[] { fnDeclarator }; declarators = new IASTStandardFunctionDeclarator[] { (IASTStandardFunctionDeclarator) fnDeclarator };
return; return;
} }
for( int i = 0; i < declarators.length; i++ ){ for( int i = 0; i < declarators.length; i++ ){
if( declarators[i] == null ){ if( declarators[i] == null ){
declarators[i] = fnDeclarator; declarators[i] = (IASTStandardFunctionDeclarator) fnDeclarator;
return; return;
} }
} }
IASTFunctionDeclarator tmp [] = new IASTFunctionDeclarator [ declarators.length * 2 ]; IASTStandardFunctionDeclarator tmp [] = new IASTStandardFunctionDeclarator [ declarators.length * 2 ];
System.arraycopy( declarators, 0, tmp, 0, declarators.length ); System.arraycopy( declarators, 0, tmp, 0, declarators.length );
tmp[ declarators.length ] = fnDeclarator; tmp[ declarators.length ] = (IASTStandardFunctionDeclarator) fnDeclarator;
declarators = tmp; declarators = tmp;
} }
} }
// private IASTFunctionDeclarator checkForDefinition( IASTFunctionDeclarator dtor ){
// if( dtor.getParent() instanceof IASTFunctionDefinition )
// return dtor;
//
// IASTFunctionDeclarator def = CVisitor.findDefinition( dtor );
// if( def != null && def != dtor ){
// dtor = def;
// ((CASTName)dtor.getName()).setBinding( this );
// }
// return dtor;
// }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IFunction#getParameters() * @see org.eclipse.cdt.core.dom.ast.IFunction#getParameters()
@ -168,7 +159,131 @@ public class CFunction implements IFunction, ICBinding {
return type; return type;
} }
// public IASTDeclaration getDeclaration(){ public IBinding resolveParameter( IASTName paramName ){
// return (IASTDeclaration) declarator.getParent(); if( ((CASTName)paramName).hasBinding() )
// } return paramName.resolveBinding();
IBinding binding = null;
int idx = 0;
IASTNode parent = paramName.getParent();
if( !(parent instanceof ICASTKnRFunctionDeclarator ) )
parent = parent.getParent();
ICASTKnRFunctionDeclarator fKnRDtor = null;
IASTDeclarator knrParamDtor = null;
if( parent instanceof IASTParameterDeclaration ){
IASTStandardFunctionDeclarator fdtor = (IASTStandardFunctionDeclarator) parent.getParent();
IASTParameterDeclaration [] ps = fdtor.getParameters();
for( ; idx < ps.length; idx++ ){
if( parent == ps[idx] )
break;
}
} else if( parent instanceof IASTSimpleDeclaration ){
//KnR: name in declaration list
fKnRDtor = (ICASTKnRFunctionDeclarator) parent.getParent();
IASTName [] ps = fKnRDtor.getParameterNames();
char [] n = paramName.toCharArray();
for( ; idx < ps.length; idx++ ){
if( CharArrayUtils.equals( ps[idx].toCharArray(), n ) )
break;
}
} else {
//KnR: name in name list
fKnRDtor = (ICASTKnRFunctionDeclarator) parent;
IASTName [] ps = fKnRDtor.getParameterNames();
for( ; idx < ps.length; idx++ ){
if( ps[idx] == paramName)
break;
}
knrParamDtor = getKnRParameterDeclarator( fKnRDtor, paramName );
paramName = knrParamDtor.getName();
}
//create a new binding and set it for the corresponding parameter in all known defns and decls
binding = new CParameter( paramName );
IASTParameterDeclaration temp = null;
if( definition != null ){
if( definition instanceof IASTStandardFunctionDeclarator ){
temp = ((IASTStandardFunctionDeclarator)definition).getParameters()[idx];
((CASTName)temp.getDeclarator().getName()).setBinding( binding );
} else if( definition instanceof ICASTKnRFunctionDeclarator ){
IASTName n = fKnRDtor.getParameterNames()[idx];
((CASTName)n).setBinding( binding );
IASTDeclarator dtor = getKnRParameterDeclarator( fKnRDtor, n );
if( dtor != null ){
((CASTName)dtor.getName()).setBinding( binding );
}
}
}
if( declarators != null ){
for( int j = 0; j < declarators.length && declarators[j] != null; j++ ){
if( declarators[j].getParameters().length > idx ){
temp = declarators[j].getParameters()[idx];
((CASTName)temp.getDeclarator().getName()).setBinding( binding );
}
}
}
return binding;
}
private IASTDeclarator getKnRParameterDeclarator( ICASTKnRFunctionDeclarator fKnRDtor, IASTName name ){
IASTDeclaration [] decls = fKnRDtor.getParameterDeclarations();
char [] n = name.toCharArray();
for( int i = 0; i < decls.length; i++ ){
if( !( decls[i] instanceof IASTSimpleDeclaration ) )
continue;
IASTDeclarator [] dtors = ((IASTSimpleDeclaration)decls[i]).getDeclarators();
for( int j = 0; j < dtors.length; j++ ){
if( CharArrayUtils.equals( dtors[j].getName().toCharArray(), n ) ){
return dtors[j];
}
}
}
return null;
}
protected void updateParameterBindings( IASTFunctionDeclarator fdtor ){
CParameter temp = null;
if( fdtor instanceof IASTStandardFunctionDeclarator ){
IASTStandardFunctionDeclarator orig = (IASTStandardFunctionDeclarator) getPhysicalNode();
IASTParameterDeclaration [] ops = orig.getParameters();
IASTParameterDeclaration [] nps = ((IASTStandardFunctionDeclarator)fdtor).getParameters();
for( int i = 0; i < nps.length; i++ ){
CASTName origname = (CASTName) ops[i].getDeclarator().getName();
if( origname.hasBinding() ){
temp = (CParameter) origname.resolveBinding();
if( temp != null ){
CASTName name = (CASTName) nps[i].getDeclarator().getName();
name.setBinding( temp );
temp.addDeclaration( name );
}
}
}
} else {
IASTParameterDeclaration [] ops = declarators[0].getParameters();
IASTName [] ns = ((ICASTKnRFunctionDeclarator)fdtor).getParameterNames();
if( ops.length > 0 && ops.length != ns.length )
return; //problem
for( int i = 0; i < ops.length; i++ ){
CASTName origname = (CASTName) ops[i].getDeclarator().getName();
if( origname.hasBinding() ){
temp = (CParameter) origname.resolveBinding();
if( temp != null ){
CASTName name = (CASTName) ns[i];
name.setBinding( temp );
IASTDeclarator dtor = getKnRParameterDeclarator( (ICASTKnRFunctionDeclarator) fdtor, name );
if( dtor != null ){
((CASTName) dtor.getName()).setBinding( temp );
temp.addDeclaration( (CASTName) dtor.getName() );
}
}
}
}
}
}
} }

View file

@ -11,79 +11,81 @@
**********************************************************************/ **********************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c; package org.eclipse.cdt.internal.core.dom.parser.c;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier; import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
/** /**
* Created on Nov 5, 2004 * Created on Nov 5, 2004
* @author aniefer * @author aniefer
*/ */
public class CParameter implements IParameter { public class CParameter implements IParameter {
final private IASTParameterDeclaration parameterDeclaration; private IASTName [] declarations;
public CParameter( IASTParameterDeclaration parameterDeclaration ){ public CParameter( IASTName parameterName ){
//parameterDeclaration = checkForDefinition( parameterDeclaration ); this.declarations = new IASTName [] { parameterName };
this.parameterDeclaration = parameterDeclaration;
} }
public IASTNode getPhysicalNode(){
return parameterDeclaration;
}
// private IASTParameterDeclaration checkForDefinition( IASTParameterDeclaration paramDecl ){
// IASTFunctionDeclarator fnDtor = (IASTFunctionDeclarator) paramDecl.getParent();
// if( fnDtor.getParent() instanceof IASTFunctionDefinition )
// return paramDecl;
//
// IASTFunctionDeclarator fDef = CVisitor.findDefinition( fnDtor );
// if( fDef != null && fDef instanceof IASTFunctionDefinition ){
// int index = fnDtor.getParameters().indexOf( paramDecl );
// if( index >= 0 && index < fDef.getParameters().size() ) {
// IASTParameterDeclaration pDef = (IASTParameterDeclaration) fDef.getParameters().get( index );
// ((CASTName)pDef.getDeclarator().getName()).setBinding( this );
// paramDecl = pDef;
// }
// }
// return paramDecl;
// }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IVariable#getType() * @see org.eclipse.cdt.core.dom.ast.IVariable#getType()
*/ */
public IType getType() { public IType getType() {
IASTDeclSpecifier declSpec = parameterDeclaration.getDeclSpecifier(); return CVisitor.createType( declarations[0], true );
if( declSpec instanceof ICASTTypedefNameSpecifier ){
ICASTTypedefNameSpecifier nameSpec = (ICASTTypedefNameSpecifier) declSpec;
return (IType) nameSpec.getName().resolveBinding();
} else if( declSpec instanceof IASTElaboratedTypeSpecifier ){
IASTElaboratedTypeSpecifier elabTypeSpec = (IASTElaboratedTypeSpecifier) declSpec;
return (IType) elabTypeSpec.getName().resolveBinding();
}
return null;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getName() * @see org.eclipse.cdt.core.dom.ast.IBinding#getName()
*/ */
public String getName() { public String getName() {
return parameterDeclaration.getDeclarator().getName().toString(); return declarations[0].toString();
} }
public char[] getNameCharArray(){ public char[] getNameCharArray(){
return ((CASTName)parameterDeclaration.getDeclarator().getName()).toCharArray(); return declarations[0].toCharArray();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/ */
public IScope getScope() { public IScope getScope() {
return CVisitor.getContainingScope( parameterDeclaration ); //IASTParameterDeclaration or IASTSimpleDeclaration
for( int i = 0; i < declarations.length; i++ ){
IASTNode parent = declarations[i].getParent();
if( parent instanceof ICASTKnRFunctionDeclarator ){
parent = parent.getParent();
return ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope();
}
IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) parent.getParent().getParent();
parent = fdtor.getParent();
if( parent instanceof IASTFunctionDefinition ) {
return ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope();
}
}
//TODO: if not definition, find definition
return null;
} }
/**
* @param name
*/
public void addDeclaration( CASTName name ) {
for( int i = 0; i < declarations.length; i++ ){
if( declarations[i] == null ){
declarations[i] = name;
return;
}
}
IASTName [] tmp = new IASTName[ declarations.length * 2 ];
System.arraycopy( declarations, 0, tmp, 0, declarations.length );
tmp[ declarations.length ] = name;
declarations = tmp;
}
} }

View file

@ -36,7 +36,6 @@ import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTForStatement; import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement; import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
@ -55,6 +54,7 @@ import org.eclipse.cdt.core.dom.ast.IASTProblemHolder;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement; import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
@ -529,7 +529,10 @@ public class CVisitor {
binding = createBinding(declarator); binding = createBinding(declarator);
} }
} else { // createBinding for one of the ICASTKnRFunctionDeclarator's parameterNames } else { // createBinding for one of the ICASTKnRFunctionDeclarator's parameterNames
binding = resolveKnRParameterBinding((ICASTKnRFunctionDeclarator) declarator, name); IBinding f = declarator.getName().resolveBinding();
if( f instanceof CFunction ){
binding = ((CFunction) f).resolveParameter( name );
}
if ( declarator.getParent() instanceof IASTFunctionDefinition ) { if ( declarator.getParent() instanceof IASTFunctionDefinition ) {
ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)declarator.getParent()).getBody()).getScope(); ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)declarator.getParent()).getBody()).getScope();
@ -540,19 +543,18 @@ public class CVisitor {
} else if( parent instanceof IASTSimpleDeclaration ){ } else if( parent instanceof IASTSimpleDeclaration ){
binding = createBinding( (IASTSimpleDeclaration) parent, name ); binding = createBinding( (IASTSimpleDeclaration) parent, name );
} else if( parent instanceof IASTParameterDeclaration ){ } else if( parent instanceof IASTParameterDeclaration ){
binding = createBinding( (IASTParameterDeclaration ) parent ); IASTParameterDeclaration param = (IASTParameterDeclaration) parent;
IASTFunctionDeclarator fDtor = (IASTFunctionDeclarator) param.getParent();
// C99 6.2.1-4: within the list of parameter declarations in a function definition, the IBinding b = fDtor.getName().resolveBinding();
// identifier has block scope, which terminates at the end of the associated block. if( b instanceof IFunction ){
parent = parent.getParent(); binding = ((CFunction)b).resolveParameter( name );
if ( parent instanceof IASTStandardFunctionDeclarator ) { parent = fDtor.getParent();
parent = parent.getParent(); if( parent instanceof IASTFunctionDefinition ){
if ( parent instanceof IASTFunctionDefinition ) { ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope();
ICScope scope = (ICScope) ((IASTCompoundStatement)((IASTFunctionDefinition)parent).getBody()).getScope();
if ( scope != null && binding != null ) if ( scope != null && binding != null )
scope.addBinding(binding); scope.addBinding(binding);
} }
} }
} else if ( parent instanceof IASTFunctionDeclarator ) { } else if ( parent instanceof IASTFunctionDeclarator ) {
binding = createBinding(declarator); binding = createBinding(declarator);
} }
@ -634,7 +636,11 @@ public class CVisitor {
if( binding == null ){ if( binding == null ){
// if the simpleDeclaration is part of a KRC function declarator, then the binding is to a KRC parameter // if the simpleDeclaration is part of a KRC function declarator, then the binding is to a KRC parameter
if ( simpleDeclaration.getParent() instanceof IASTFunctionDeclarator ) { if ( simpleDeclaration.getParent() instanceof IASTFunctionDeclarator ) {
binding = resolveKnRParameterBinding((ICASTKnRFunctionDeclarator) simpleDeclaration.getParent(), name); // is resolveKnRParameterBinding still necessary? IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) simpleDeclaration.getParent();
IBinding fn = fdtor.getName().resolveBinding();
if( fn instanceof CFunction ){
binding = ((CFunction)fn).resolveParameter( name );
}
} else { } else {
binding = new CVariable( name ); binding = new CVariable( name );
} }
@ -646,13 +652,6 @@ public class CVisitor {
return binding; return binding;
} }
private static IBinding createBinding( IASTParameterDeclaration parameterDeclaration ){
IBinding binding = resolveBinding( parameterDeclaration, CURRENT_SCOPE );
if( binding == null )
binding = new CParameter( parameterDeclaration );
return binding;
}
protected static IBinding resolveBinding( IASTNode node ){ protected static IBinding resolveBinding( IASTNode node ){
return resolveBinding( node, COMPLETE ); return resolveBinding( node, COMPLETE );
} }
@ -675,23 +674,6 @@ public class CVisitor {
} else if( node instanceof ICASTCompositeTypeSpecifier ){ } else if( node instanceof ICASTCompositeTypeSpecifier ){
IASTNode blockItem = getContainingBlockItem( node ); IASTNode blockItem = getContainingBlockItem( node );
return findBinding( blockItem, ((ICASTCompositeTypeSpecifier)node).getName(), bits ); return findBinding( blockItem, ((ICASTCompositeTypeSpecifier)node).getName(), bits );
} else if( node instanceof IASTParameterDeclaration ){
IASTParameterDeclaration param = (IASTParameterDeclaration) node;
IASTStandardFunctionDeclarator fDtor = (IASTStandardFunctionDeclarator) param.getParent();
if ( fDtor.getName().resolveBinding() instanceof IFunction ) { // possible to have IASTParameterDeclaration whose parent is an IVariable
IFunction function = (IFunction) fDtor.getName().resolveBinding();
if( ((ICBinding)function).getPhysicalNode() != fDtor ) {
IASTParameterDeclaration [] ps = fDtor.getParameters();
int index = -1;
for( index = 0; index < ps.length; index++ )
if( ps[index] == param ) break;
IParameter [] params = function.getParameters();
if( index >= 0 && index < params.length ){
return params[ index ];
}
}
}
} else if( node instanceof IASTTypeId ){ } else if( node instanceof IASTTypeId ){
IASTTypeId typeId = (IASTTypeId) node; IASTTypeId typeId = (IASTTypeId) node;
IASTDeclSpecifier declSpec = typeId.getDeclSpecifier(); IASTDeclSpecifier declSpec = typeId.getDeclSpecifier();
@ -1693,44 +1675,4 @@ public class CVisitor {
return action.getDeclarationNames(); return action.getDeclarationNames();
} }
private static IBinding resolveKnRParameterBinding(ICASTKnRFunctionDeclarator declarator, IASTName name) {
IASTDeclaration[] parmDeclarations = declarator.getParameterDeclarations();
if ( declarator.getName().resolveBinding() instanceof IFunction ) { // possible to have IASTParameterDeclaration whose parent is an IVariable
IFunction function = (IFunction) declarator.getName().resolveBinding();
if( ((ICBinding)function).getPhysicalNode() != declarator ) {
IASTDeclaration [] ps = declarator.getParameterDeclarations();
int index = -1;
outerLoop: for( index = 0; index < ps.length; index++ )
for (int j=0; j<parmDeclarations.length; j++)
if( ps[index] == parmDeclarations[j] ) break outerLoop;
IParameter[] params = function.getParameters();
if( index >= 0 && index < params.length ){
return params[ index ];
}
}
}
for (int i=0; i<parmDeclarations.length; i++) {
if ( parmDeclarations[i] instanceof IASTSimpleDeclaration ) {
IASTDeclarator[] decltors = ((IASTSimpleDeclaration)parmDeclarations[i]).getDeclarators();
for (int j=0; j<decltors.length; j++) {
if (CharArrayUtils.equals( decltors[j].getName().toCharArray(), name.toCharArray()) ) {
if (decltors[j].getName() instanceof CASTName && ((CASTName)decltors[j].getName()).hasBinding())
return decltors[j].getName().resolveBinding();
return new CKnRParameter( parmDeclarations[i], decltors[j].getName() );
}
}
}
}
// NOTE: without a function prototype a parameter name without a matching declaration currently resolves to a null binding
// i.e. int f(x,y) char x; {} // this compiles/runs, but does not compile when the prototype is included
return null; // nothing found
}
} }