1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Function declarations with typedefs in C, bug 86495.

This commit is contained in:
Markus Schorn 2009-11-02 14:31:18 +00:00
parent 64bae1cd11
commit e620619660
5 changed files with 200 additions and 183 deletions

View file

@ -7028,4 +7028,20 @@ public class AST2Tests extends AST2BaseTest {
f= bh.assertNonProblem("f2", 2); f= bh.assertNonProblem("f2", 2);
assertEquals("const int *", ASTTypeUtil.getType(f.getParameters()[0].getType())); assertEquals("const int *", ASTTypeUtil.getType(f.getParameters()[0].getType()));
} }
// typedef int f();
// f ff;
// int ff() { return 0;}
public void testFunctionDeclViaTypedef_86495() throws Exception {
final String code = getAboveComment();
// for(ParserLanguage lang : ParserLanguage.values()) {
// IASTTranslationUnit tu = parseAndCheckBindings(code, lang);
IASTTranslationUnit tu = parseAndCheckBindings(code, ParserLanguage.C);
IASTSimpleDeclaration decl= getDeclaration(tu, 1);
IASTFunctionDefinition def= getDeclaration(tu, 2);
IBinding ffDecl= decl.getDeclarators()[0].getName().resolveBinding();
IBinding ffDef= def.getDeclarator().getName().resolveBinding();
assertSame(ffDecl, ffDef);
// }
}
} }

View file

@ -17,7 +17,7 @@ package org.eclipse.cdt.core.parser.util;
import java.lang.reflect.Array; import java.lang.reflect.Array;
/** /**
* @noextend This interface is not intended to be extended by clients. * @noextend This class is not intended to be subclassed by clients.
*/ */
public abstract class ArrayUtil { public abstract class ArrayUtil {
private static final int DEFAULT_LENGTH = 2; private static final int DEFAULT_LENGTH = 2;

View file

@ -42,7 +42,7 @@ import org.eclipse.core.runtime.PlatformObject;
* Represents a function. * Represents a function.
*/ */
public class CFunction extends PlatformObject implements IFunction, ICInternalFunction { public class CFunction extends PlatformObject implements IFunction, ICInternalFunction {
private IASTStandardFunctionDeclarator [] declarators = null; private IASTDeclarator[] declarators = null;
private IASTFunctionDeclarator definition; private IASTFunctionDeclarator definition;
private static final int FULLY_RESOLVED = 1; private static final int FULLY_RESOLVED = 1;
@ -51,52 +51,40 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
protected IFunctionType type = null; protected IFunctionType type = null;
public CFunction( IASTFunctionDeclarator declarator ){ public CFunction(IASTDeclarator declarator) {
if( declarator != null ) { storeDeclarator(declarator);
if( declarator.getParent() instanceof IASTFunctionDefinition || declarator instanceof ICASTKnRFunctionDeclarator ) }
definition = declarator;
else { private void storeDeclarator(IASTDeclarator declarator) {
declarators = new IASTStandardFunctionDeclarator [] { (IASTStandardFunctionDeclarator) declarator }; if (declarator != null) {
} if (declarator instanceof ICASTKnRFunctionDeclarator) {
definition = (IASTFunctionDeclarator) declarator;
} else if (declarator instanceof IASTFunctionDeclarator
&& ASTQueries.findOutermostDeclarator(declarator).getParent() instanceof IASTFunctionDefinition) {
definition = (IASTFunctionDeclarator) declarator;
} else {
declarators = (IASTDeclarator[]) ArrayUtil.append(IASTDeclarator.class, declarators, declarator);
}
} }
} }
public IASTNode getPhysicalNode(){ public IASTDeclarator getPhysicalNode() {
if( definition != null ) if (definition != null)
return definition; return definition;
else if( declarators != null && declarators.length > 0 ) else if (declarators != null && declarators.length > 0)
return declarators[0]; return declarators[0];
return null; return null;
} }
public void addDeclarator( IASTFunctionDeclarator fnDeclarator ){
if (!fnDeclarator.isActive())
return;
if( fnDeclarator.getParent() instanceof IASTFunctionDefinition || fnDeclarator instanceof ICASTKnRFunctionDeclarator ) { public void addDeclarator(IASTDeclarator fnDeclarator) {
if (definition == fnDeclarator) { if (!fnDeclarator.isActive())
// recursion?
return;
}
updateParameterBindings( fnDeclarator );
definition = fnDeclarator;
return;
}
updateParameterBindings( fnDeclarator );
if( declarators == null ){
declarators = new IASTStandardFunctionDeclarator[] { (IASTStandardFunctionDeclarator) fnDeclarator };
return; return;
if (fnDeclarator instanceof IASTFunctionDeclarator) {
updateParameterBindings((IASTFunctionDeclarator) fnDeclarator);
} }
for( int i = 0; i < declarators.length; i++ ){ storeDeclarator(fnDeclarator);
if( declarators[i] == null ){ }
declarators[i] = (IASTStandardFunctionDeclarator) fnDeclarator;
return;
}
}
IASTStandardFunctionDeclarator tmp [] = new IASTStandardFunctionDeclarator [ declarators.length * 2 ];
System.arraycopy( declarators, 0, tmp, 0, declarators.length );
tmp[ declarators.length ] = (IASTStandardFunctionDeclarator) fnDeclarator;
declarators = tmp;
}
protected IASTTranslationUnit getTranslationUnit() { protected IASTTranslationUnit getTranslationUnit() {
if( definition != null ) if( definition != null )
@ -113,7 +101,7 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
if( tu != null ){ if( tu != null ){
CVisitor.getDeclarations( tu, this ); CVisitor.getDeclarations( tu, this );
} }
declarators = (IASTStandardFunctionDeclarator[]) ArrayUtil.trim( IASTStandardFunctionDeclarator.class, declarators ); declarators = (IASTDeclarator[]) ArrayUtil.trim(IASTDeclarator.class, declarators);
bits |= FULLY_RESOLVED; bits |= FULLY_RESOLVED;
bits &= ~RESOLUTION_IN_PROGRESS; bits &= ~RESOLUTION_IN_PROGRESS;
} }
@ -123,41 +111,53 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
* @see org.eclipse.cdt.core.dom.ast.IFunction#getParameters() * @see org.eclipse.cdt.core.dom.ast.IFunction#getParameters()
*/ */
public IParameter[] getParameters() { public IParameter[] getParameters() {
IParameter [] result = IParameter.EMPTY_PARAMETER_ARRAY; int j=-1;
int len = declarators != null ? declarators.length : 0;
IASTFunctionDeclarator dtor = (IASTFunctionDeclarator) getPhysicalNode(); for (IASTDeclarator dtor = definition; j < len; j++) {
if( dtor == null && (bits & FULLY_RESOLVED) == 0){ if (j >= 0) {
resolveAllDeclarations(); dtor = declarators[j];
dtor = (IASTFunctionDeclarator) getPhysicalNode();
}
if (dtor instanceof IASTStandardFunctionDeclarator) {
IASTParameterDeclaration[] params = ((IASTStandardFunctionDeclarator)dtor).getParameters();
int size = params.length;
result = new IParameter[ size ];
if( size > 0 ){
for( int i = 0; i < size; i++ ){
IASTParameterDeclaration p = params[i];
result[i] = (IParameter) ASTQueries.findInnermostDeclarator(p.getDeclarator()).getName().resolveBinding();
}
} }
} else if (dtor instanceof ICASTKnRFunctionDeclarator) { if (dtor instanceof IASTStandardFunctionDeclarator) {
IASTName[] names = ((ICASTKnRFunctionDeclarator)dtor).getParameterNames(); IASTParameterDeclaration[] params = ((IASTStandardFunctionDeclarator) dtor).getParameters();
result = new IParameter[ names.length ]; int size = params.length;
if( names.length > 0 ){ IParameter[] result = new IParameter[size];
// ensures that the List of parameters is created in the same order as the K&R C parameter names if (size > 0) {
for( int i=0; i<names.length; i++ ) { for (int i = 0; i < size; i++) {
IASTDeclarator decl = CVisitor.getKnRParameterDeclarator( (ICASTKnRFunctionDeclarator) dtor, names[i] ); IASTParameterDeclaration p = params[i];
if( decl != null ) { result[i] = (IParameter) ASTQueries.findInnermostDeclarator(p.getDeclarator())
result[i] = (IParameter) decl.getName().resolveBinding(); .getName().resolveBinding();
} else { }
result[i] = new CParameter.CParameterProblem( names[i], IProblemBinding.SEMANTIC_KNR_PARAMETER_DECLARATION_NOT_FOUND, names[i].toCharArray() );
}
} }
return result;
}
if (dtor instanceof ICASTKnRFunctionDeclarator) {
IASTName[] names = ((ICASTKnRFunctionDeclarator) dtor).getParameterNames();
IParameter[] result = new IParameter[names.length];
if (names.length > 0) {
// Ensures that the list of parameters is created in the same order as the K&R C parameter
// names
for (int i = 0; i < names.length; i++) {
IASTDeclarator decl = CVisitor.getKnRParameterDeclarator(
(ICASTKnRFunctionDeclarator) dtor, names[i]);
if (decl != null) {
result[i] = (IParameter) decl.getName().resolveBinding();
} else {
result[i] = new CParameter.CParameterProblem(names[i],
IProblemBinding.SEMANTIC_KNR_PARAMETER_DECLARATION_NOT_FOUND, names[i]
.toCharArray());
}
}
}
return result;
} }
} }
return result; if ((bits & (FULLY_RESOLVED | RESOLUTION_IN_PROGRESS)) == 0) {
resolveAllDeclarations();
return getParameters();
}
return IParameter.EMPTY_PARAMETER_ARRAY;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -172,22 +172,16 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
} }
private IASTName getASTName() { private IASTName getASTName() {
IASTDeclarator dtor = ( definition != null ) ? definition : declarators[0]; return ASTQueries.findInnermostDeclarator(getPhysicalNode()).getName();
IASTDeclarator nested= dtor.getNestedDeclarator();
while (nested != null && nested.getPointerOperators().length == 0) {
dtor= nested;
nested= nested.getNestedDeclarator();
}
return dtor.getName();
} }
/* (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() {
IASTFunctionDeclarator dtor = (IASTFunctionDeclarator) getPhysicalNode(); IASTDeclarator dtor = getPhysicalNode();
if( dtor != null ) if (dtor != null)
return CVisitor.getContainingScope( dtor.getParent() ); return CVisitor.getContainingScope(ASTQueries.findOutermostDeclarator(dtor).getParent());
return null; return null;
} }
@ -195,7 +189,7 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
* @see org.eclipse.cdt.core.dom.ast.IFunction#getFunctionScope() * @see org.eclipse.cdt.core.dom.ast.IFunction#getFunctionScope()
*/ */
public IScope getFunctionScope() { public IScope getFunctionScope() {
if( definition != null ){ if (definition != null) {
IASTFunctionDefinition def = (IASTFunctionDefinition) definition.getParent(); IASTFunctionDefinition def = (IASTFunctionDefinition) definition.getParent();
return def.getScope(); return def.getScope();
} }
@ -205,25 +199,21 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IFunction#getType() * @see org.eclipse.cdt.core.dom.ast.IFunction#getType()
*/ */
public IFunctionType getType() { public IFunctionType getType() {
if( type == null ) { if (type == null) {
IASTDeclarator functionDtor = (IASTDeclarator) getPhysicalNode(); IASTDeclarator declarator = getPhysicalNode();
if( functionDtor == null && (bits & FULLY_RESOLVED) == 0){ if (declarator == null && (bits & FULLY_RESOLVED) == 0) {
resolveAllDeclarations(); resolveAllDeclarations();
functionDtor = (IASTDeclarator) getPhysicalNode(); declarator = getPhysicalNode();
} }
if( functionDtor != null ) { if (declarator != null) {
while (functionDtor.getNestedDeclarator() != null) IType tempType = CVisitor.unwrapTypedefs(CVisitor.createType(declarator));
functionDtor = functionDtor.getNestedDeclarator(); if (tempType instanceof IFunctionType)
type = (IFunctionType) tempType;
IType tempType = CVisitor.createType( functionDtor ); }
if (tempType instanceof IFunctionType) }
type = (IFunctionType)tempType; return type;
} }
}
return type;
}
public IBinding resolveParameter( IASTName paramName ){ public IBinding resolveParameter( IASTName paramName ){
if( paramName.getBinding() != null ) if( paramName.getBinding() != null )
@ -289,12 +279,15 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
} }
} }
} }
if( declarators != null ){ if (declarators != null) {
for( int j = 0; j < declarators.length && declarators[j] != null; j++ ){ for (IASTDeclarator dtor : declarators) {
if( declarators[j].getParameters().length > idx ){ if (dtor instanceof IASTStandardFunctionDeclarator) {
temp = declarators[j].getParameters()[idx]; IASTStandardFunctionDeclarator fdtor= (IASTStandardFunctionDeclarator) dtor;
ASTQueries.findInnermostDeclarator(temp.getDeclarator()).getName().setBinding( binding ); if( fdtor.getParameters().length > idx ){
} temp = fdtor.getParameters()[idx];
ASTQueries.findInnermostDeclarator(temp.getDeclarator()).getName().setBinding( binding );
}
}
} }
} }
return binding; return binding;
@ -437,22 +430,26 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
} }
public boolean takesVarArgs() { public boolean takesVarArgs() {
if( (bits & FULLY_RESOLVED) == 0 ){ if ((bits & FULLY_RESOLVED) == 0) {
resolveAllDeclarations(); resolveAllDeclarations();
} }
if( definition != null ){ if (definition != null) {
if( definition instanceof IASTStandardFunctionDeclarator ) if (definition instanceof IASTStandardFunctionDeclarator)
return ((IASTStandardFunctionDeclarator)definition).takesVarArgs(); return ((IASTStandardFunctionDeclarator) definition).takesVarArgs();
return false; return false;
} }
if( declarators != null && declarators.length > 0 ){ if (declarators != null) {
return declarators[0].takesVarArgs(); for (IASTDeclarator dtor : declarators) {
} if (dtor instanceof IASTStandardFunctionDeclarator) {
return false; return ((IASTStandardFunctionDeclarator) dtor).takesVarArgs();
} }
}
}
return false;
}
public void setFullyResolved(boolean resolved) { public void setFullyResolved(boolean resolved) {
if( resolved ) if( resolved )

View file

@ -689,7 +689,7 @@ public class CVisitor extends ASTQueries {
} }
if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) { if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) {
if (binding instanceof ICInternalFunction) if (binding instanceof ICInternalFunction)
((ICInternalFunction)binding).addDeclarator((ICASTKnRFunctionDeclarator) declarator); ((ICInternalFunction)binding).addDeclarator(declarator);
else else
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray()); binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray());
} else { } else {
@ -708,17 +708,9 @@ public class CVisitor extends ASTQueries {
} }
private static IBinding createBinding(IASTDeclarator declarator) { private static IBinding createBinding(IASTDeclarator declarator) {
IASTNode parent = declarator.getParent(); IASTNode parent = ASTQueries.findOutermostDeclarator(declarator).getParent();
while (parent instanceof IASTDeclarator) {
parent = parent.getParent();
}
declarator= ASTQueries.findInnermostDeclarator(declarator); declarator= ASTQueries.findInnermostDeclarator(declarator);
IASTDeclarator typeRelevant= ASTQueries.findTypeRelevantDeclarator(declarator); IASTDeclarator typeRelevant= ASTQueries.findTypeRelevantDeclarator(declarator);
IASTFunctionDeclarator funcDeclarator= null;
if (typeRelevant instanceof IASTFunctionDeclarator) {
funcDeclarator= (IASTFunctionDeclarator) typeRelevant;
}
IScope scope= getContainingScope(parent); IScope scope= getContainingScope(parent);
ASTNodeProperty prop = parent.getPropertyInParent(); ASTNodeProperty prop = parent.getPropertyInParent();
@ -737,6 +729,7 @@ public class CVisitor extends ASTQueries {
} catch (DOMException e1) { } catch (DOMException e1) {
} }
boolean isFunction= false;
if (parent instanceof IASTParameterDeclaration || parent.getPropertyInParent() == ICASTKnRFunctionDeclarator.FUNCTION_PARAMETER) { if (parent instanceof IASTParameterDeclaration || parent.getPropertyInParent() == ICASTKnRFunctionDeclarator.FUNCTION_PARAMETER) {
IASTDeclarator fdtor = (IASTDeclarator) parent.getParent(); IASTDeclarator fdtor = (IASTDeclarator) parent.getParent();
if (ASTQueries.findTypeRelevantDeclarator(fdtor) instanceof IASTFunctionDeclarator) { if (ASTQueries.findTypeRelevantDeclarator(fdtor) instanceof IASTFunctionDeclarator) {
@ -750,50 +743,59 @@ public class CVisitor extends ASTQueries {
} }
return binding; return binding;
} }
} else if (funcDeclarator != null) { } else if (parent instanceof IASTFunctionDefinition) {
if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) { isFunction= true;
if (binding instanceof IFunction) {
IFunction function = (IFunction) binding;
if (function instanceof CFunction) {
((CFunction)function).addDeclarator(funcDeclarator);
}
return function;
}
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray());
} else if (parent instanceof IASTSimpleDeclaration && ((IASTSimpleDeclaration) parent).getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef)
binding = new CTypedef(name);
else
binding = new CFunction(funcDeclarator);
} else if (parent instanceof IASTSimpleDeclaration) { } else if (parent instanceof IASTSimpleDeclaration) {
IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent; IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) parent;
if (simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) { if (simpleDecl.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef) {
binding = new CTypedef(name); binding = new CTypedef(name);
} else { } else {
IType t1 = null, t2 = null; isFunction= typeRelevant instanceof IASTFunctionDeclarator;
if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) { if (!isFunction) {
if (binding instanceof IParameter) { IType t1 = createType(declarator), t2 = null;
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray()); if (CVisitor.unwrapTypedefs(t1) instanceof IFunctionType) {
} else if (binding instanceof IVariable) { isFunction= true;
t1 = createType(declarator); } else {
try { if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) {
t2 = ((IVariable)binding).getType(); if (binding instanceof IParameter) {
} catch (DOMException e1) { return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray());
} } else if (binding instanceof IVariable) {
if (t1 != null && t2 != null && ( try {
t1.isSameType(t2) || isCompatibleArray(t1, t2) != null)) { t2 = ((IVariable)binding).getType();
if (binding instanceof CVariable) } catch (DOMException e1) {
((CVariable)binding).addDeclaration(name); }
} else { if (t1 != null && t2 != null && (
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray()); t1.isSameType(t2) || isCompatibleArray(t1, t2) != null)) {
} if (binding instanceof CVariable)
} ((CVariable)binding).addDeclaration(name);
} else if (simpleDecl.getParent() instanceof ICASTCompositeTypeSpecifier) { } else {
binding = new CField(name); return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray());
} else { }
binding = new CVariable(name); }
} else if (simpleDecl.getParent() instanceof ICASTCompositeTypeSpecifier) {
binding = new CField(name);
} else {
binding = new CVariable(name);
}
}
} }
} }
} }
if (isFunction) {
if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) {
if (binding instanceof IFunction) {
IFunction function = (IFunction) binding;
if (function instanceof CFunction) {
((CFunction)function).addDeclarator(typeRelevant);
}
return function;
}
binding = new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray());
} else {
binding = new CFunction(typeRelevant);
}
}
return binding; return binding;
} }

View file

@ -12,19 +12,21 @@
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.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
/** /**
* Interface for ast-internal implementations of function bindings. * Interface for ast-internal implementations of function bindings.
*/ */
public interface ICInternalFunction extends ICInternalBinding { public interface ICInternalFunction extends ICInternalBinding {
public void setFullyResolved( boolean resolved ); public void setFullyResolved(boolean resolved);
public void addDeclarator( IASTFunctionDeclarator fnDeclarator ); public void addDeclarator(IASTDeclarator fnDeclarator);
/** /**
* Returns whether there is a static declaration for this function. * Returns whether there is a static declaration for this function.
* @param resolveAll checks for names that are not yet resolved to this binding. *
*/ * @param resolveAll
public boolean isStatic(boolean resolveAll); * checks for names that are not yet resolved to this binding.
*/
public boolean isStatic(boolean resolveAll);
} }