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,51 +51,39 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
protected IFunctionType type = null; protected IFunctionType type = null;
public CFunction( IASTFunctionDeclarator declarator ){ public CFunction(IASTDeclarator declarator) {
storeDeclarator(declarator);
}
private void storeDeclarator(IASTDeclarator declarator) {
if (declarator != null) { if (declarator != null) {
if( declarator.getParent() instanceof IASTFunctionDefinition || declarator instanceof ICASTKnRFunctionDeclarator ) if (declarator instanceof ICASTKnRFunctionDeclarator) {
definition = declarator; definition = (IASTFunctionDeclarator) declarator;
else { } else if (declarator instanceof IASTFunctionDeclarator
declarators = new IASTStandardFunctionDeclarator [] { (IASTStandardFunctionDeclarator) declarator }; && 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 ){
public void addDeclarator(IASTDeclarator fnDeclarator) {
if (!fnDeclarator.isActive()) if (!fnDeclarator.isActive())
return; return;
if( fnDeclarator.getParent() instanceof IASTFunctionDefinition || fnDeclarator instanceof ICASTKnRFunctionDeclarator ) { if (fnDeclarator instanceof IASTFunctionDeclarator) {
if (definition == fnDeclarator) { updateParameterBindings((IASTFunctionDeclarator) fnDeclarator);
// recursion?
return;
} }
updateParameterBindings( fnDeclarator ); storeDeclarator(fnDeclarator);
definition = fnDeclarator;
return;
}
updateParameterBindings( fnDeclarator );
if( declarators == null ){
declarators = new IASTStandardFunctionDeclarator[] { (IASTStandardFunctionDeclarator) fnDeclarator };
return;
}
for( int i = 0; i < declarators.length; i++ ){
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() {
@ -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) { if (dtor instanceof IASTStandardFunctionDeclarator) {
IASTParameterDeclaration[] params = ((IASTStandardFunctionDeclarator) dtor).getParameters(); IASTParameterDeclaration[] params = ((IASTStandardFunctionDeclarator) dtor).getParameters();
int size = params.length; int size = params.length;
result = new IParameter[ size ]; IParameter[] result = new IParameter[size];
if (size > 0) { if (size > 0) {
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
IASTParameterDeclaration p = params[i]; IASTParameterDeclaration p = params[i];
result[i] = (IParameter) ASTQueries.findInnermostDeclarator(p.getDeclarator()).getName().resolveBinding(); result[i] = (IParameter) ASTQueries.findInnermostDeclarator(p.getDeclarator())
.getName().resolveBinding();
} }
} }
} else if (dtor instanceof ICASTKnRFunctionDeclarator) { return result;
}
if (dtor instanceof ICASTKnRFunctionDeclarator) {
IASTName[] names = ((ICASTKnRFunctionDeclarator) dtor).getParameterNames(); IASTName[] names = ((ICASTKnRFunctionDeclarator) dtor).getParameterNames();
result = new IParameter[ names.length ]; IParameter[] result = new IParameter[names.length];
if (names.length > 0) { if (names.length > 0) {
// ensures that the List of parameters is created in the same order as the K&R C parameter names // 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++) { for (int i = 0; i < names.length; i++) {
IASTDeclarator decl = CVisitor.getKnRParameterDeclarator( (ICASTKnRFunctionDeclarator) dtor, names[i] ); IASTDeclarator decl = CVisitor.getKnRParameterDeclarator(
(ICASTKnRFunctionDeclarator) dtor, names[i]);
if (decl != null) { if (decl != null) {
result[i] = (IParameter) decl.getName().resolveBinding(); result[i] = (IParameter) decl.getName().resolveBinding();
} else { } else {
result[i] = new CParameter.CParameterProblem( names[i], IProblemBinding.SEMANTIC_KNR_PARAMETER_DECLARATION_NOT_FOUND, names[i].toCharArray() ); 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;
} }
@ -207,21 +201,17 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
*/ */
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();
IType tempType = CVisitor.createType( functionDtor );
if (tempType instanceof IFunctionType) if (tempType instanceof IFunctionType)
type = (IFunctionType) tempType; type = (IFunctionType) tempType;
} }
} }
return type; return type;
} }
@ -290,13 +280,16 @@ 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;
if( fdtor.getParameters().length > idx ){
temp = fdtor.getParameters()[idx];
ASTQueries.findInnermostDeclarator(temp.getDeclarator()).getName().setBinding( binding ); ASTQueries.findInnermostDeclarator(temp.getDeclarator()).getName().setBinding( binding );
} }
} }
} }
}
return binding; return binding;
} }
@ -448,8 +441,12 @@ public class CFunction extends PlatformObject implements IFunction, ICInternalFu
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 ((IASTStandardFunctionDeclarator) dtor).takesVarArgs();
}
}
} }
return false; return false;
} }

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,31 +743,23 @@ 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 (!isFunction) {
IType t1 = createType(declarator), t2 = null;
if (CVisitor.unwrapTypedefs(t1) instanceof IFunctionType) {
isFunction= true;
} else {
if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) { if (binding != null && !(binding instanceof IIndexBinding) && name.isActive()) {
if (binding instanceof IParameter) { if (binding instanceof IParameter) {
return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray()); return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_REDECLARATION, name.toCharArray());
} else if (binding instanceof IVariable) { } else if (binding instanceof IVariable) {
t1 = createType(declarator);
try { try {
t2 = ((IVariable)binding).getType(); t2 = ((IVariable)binding).getType();
} catch (DOMException e1) { } catch (DOMException e1) {
@ -794,6 +779,23 @@ public class CVisitor extends ASTQueries {
} }
} }
} }
}
}
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,7 +12,7 @@
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.
@ -20,11 +20,13 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
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
* checks for names that are not yet resolved to this binding.
*/ */
public boolean isStatic(boolean resolveAll); public boolean isStatic(boolean resolveAll);
} }