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);
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;
/**
* @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 {
private static final int DEFAULT_LENGTH = 2;

View file

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

View file

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

View file

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