1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 02:06:01 +02:00

GCC allows forward declarations of enums in C

This commit is contained in:
Andrew Niefer 2005-02-01 20:42:04 +00:00
parent b3ecffbb72
commit 04d743c153
4 changed files with 142 additions and 19 deletions

View file

@ -55,6 +55,7 @@ import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.ILabel; import org.eclipse.cdt.core.dom.ast.ILabel;
import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IQualifierType;
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;
@ -2600,4 +2601,22 @@ public class AST2Tests extends AST2BaseTest {
assertEquals( ps.length, 1 ); assertEquals( ps.length, 1 );
ps[0].getMessage(); ps[0].getMessage();
} }
public void testEnumerationForwards() throws Exception{
StringBuffer buffer = new StringBuffer();
buffer.append( "enum e; \n;" ); //$NON-NLS-1$
buffer.append( "enum e{ one }; \n;" ); //$NON-NLS-1$
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.C);
CNameCollector col = new CNameCollector();
CVisitor.visitTranslationUnit(tu, col);
assertEquals(col.size(), 3);
IEnumeration e = (IEnumeration) col.getName(0).resolveBinding();
IEnumerator[] etors = e.getEnumerators();
assertTrue( etors.length == 1 );
assertFalse( etors[0] instanceof IProblemBinding );
assertInstances( col, e, 2 );
}
} }

View file

@ -14,12 +14,18 @@
*/ */
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.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
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.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
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.ICASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier;
/** /**
@ -27,34 +33,75 @@ import org.eclipse.cdt.core.dom.ast.c.ICASTEnumerationSpecifier;
*/ */
public class CEnumeration implements IEnumeration { public class CEnumeration implements IEnumeration {
private final ICASTEnumerationSpecifier enumSpec; private IASTName [] declarations = null;
public CEnumeration( ICASTEnumerationSpecifier spec ){ private IASTName definition = null;
spec = checkForDefinition( spec ); public CEnumeration( IASTName enum ){
this.enumSpec = spec; ASTNodeProperty prop = enum.getPropertyInParent();
if( prop == IASTElaboratedTypeSpecifier.TYPE_NAME )
declarations = new IASTName[] { enum };
else
definition = enum;
}
public void addDeclaration( IASTName decl ){
if( decl.getPropertyInParent() != IASTElaboratedTypeSpecifier.TYPE_NAME )
return;
if( declarations == null ){
declarations = new IASTName[] { decl };
return;
}
for( int i = 0; i < declarations.length; i++ ){
if( declarations[i] == null ){
declarations[i] = decl;
return;
}
}
IASTName tmp [] = new IASTName [ declarations.length * 2 ];
System.arraycopy( declarations, 0, tmp, 0, declarations.length );
tmp[ declarations.length ] = decl;
declarations = tmp;
} }
public IASTNode getPhysicalNode(){ public IASTNode getPhysicalNode(){
return enumSpec; if( definition != null )
return definition;
return declarations[0];
} }
private ICASTEnumerationSpecifier checkForDefinition( ICASTEnumerationSpecifier spec ){
return spec; private void checkForDefinition(){
IASTDeclSpecifier spec = CVisitor.findDefinition( (ICASTElaboratedTypeSpecifier) declarations[0].getParent() );
if( spec != null && spec instanceof ICASTEnumerationSpecifier ){
ICASTEnumerationSpecifier enumSpec = (ICASTEnumerationSpecifier) spec;
((CASTName)enumSpec.getName()).setBinding( this );
definition = enumSpec.getName();
}
return;
} }
/* (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 enumSpec.getName().toString(); if( definition != null )
return definition.toString();
return declarations[0].toString();
} }
public char[] getNameCharArray(){ public char[] getNameCharArray(){
return ((CASTName) enumSpec.getName()).toCharArray(); if( definition != null )
return definition.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( enumSpec ); return CVisitor.getContainingScope( definition != null ? definition : declarations[0].getParent() );
} }
public Object clone(){ public Object clone(){
@ -71,6 +118,13 @@ public class CEnumeration implements IEnumeration {
* @see org.eclipse.cdt.core.dom.ast.IEnumeration#getEnumerators() * @see org.eclipse.cdt.core.dom.ast.IEnumeration#getEnumerators()
*/ */
public IEnumerator[] getEnumerators() { public IEnumerator[] getEnumerators() {
if( definition == null ){
checkForDefinition();
if( definition == null )
return new IEnumerator[] { new CEnumerator.CEnumeratorProblem( IProblemBinding.SEMANTIC_DEFINITION_NOT_FOUND, declarations[0].toCharArray() ) };
}
IASTEnumerationSpecifier enumSpec = (IASTEnumerationSpecifier) definition.getParent();
IASTEnumerationSpecifier.IASTEnumerator[] enums = enumSpec.getEnumerators(); IASTEnumerationSpecifier.IASTEnumerator[] enums = enumSpec.getEnumerators();
IEnumerator [] bindings = new IEnumerator [ enums.length ]; IEnumerator [] bindings = new IEnumerator [ enums.length ];
@ -79,4 +133,11 @@ public class CEnumeration implements IEnumeration {
} }
return bindings; return bindings;
} }
/**
* @param name
*/
public void addDefinition( IASTName name ) {
definition = name;
}
} }

View file

@ -14,6 +14,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.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumeration;
@ -21,11 +22,21 @@ import org.eclipse.cdt.core.dom.ast.IEnumerator;
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.IASTEnumerationSpecifier.IASTEnumerator; import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
/** /**
* @author aniefer * @author aniefer
*/ */
public class CEnumerator implements IEnumerator { public class CEnumerator implements IEnumerator {
public static class CEnumeratorProblem extends ProblemBinding implements IEnumerator {
public CEnumeratorProblem( int id, char[] arg ) {
super( id, arg );
}
public IType getType() throws DOMException {
throw new DOMException( this );
}
}
private final IASTEnumerator enumerator; private final IASTEnumerator enumerator;
public CEnumerator( IASTEnumerator enumtor ){ public CEnumerator( IASTEnumerator enumtor ){

View file

@ -98,6 +98,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.c.ICASTKnRFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator; import org.eclipse.cdt.core.dom.ast.gnu.c.IGCCASTArrayRangeDesignator;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPVisitor.CPPBaseVisitorAction;
/** /**
@ -502,10 +503,25 @@ public class CVisitor {
} }
private static IBinding createBinding( ICASTEnumerationSpecifier enumeration ){ private static IBinding createBinding( ICASTEnumerationSpecifier enumeration ){
IEnumeration binding = new CEnumeration( enumeration ); IASTName name = enumeration.getName();
ICScope scope = (ICScope) getContainingScope( enumeration );
IBinding binding;
try { try {
((ICScope)binding.getScope()).addBinding( binding ); binding = scope.getBinding( ICScope.NAMESPACE_TYPE_TAG, name.toCharArray() );
} catch ( DOMException e ) { } catch ( DOMException e ) {
binding = null;
}
if( binding != null ){
if( binding instanceof CEnumeration )
((CEnumeration)binding).addDefinition( name );
else
return new ProblemBinding(IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray() );
} else {
binding = new CEnumeration( name );
try {
scope.addBinding( binding );
} catch ( DOMException e1 ) {
}
} }
return binding; return binding;
} }
@ -551,10 +567,19 @@ public class CVisitor {
//forward declaration //forward declaration
IBinding binding = resolveBinding( elabTypeSpec, CURRENT_SCOPE | TAGS ); IBinding binding = resolveBinding( elabTypeSpec, CURRENT_SCOPE | TAGS );
if( binding == null ){ if( binding == null ){
if( elabTypeSpec.getKind() == IASTElaboratedTypeSpecifier.k_enum ){
binding = new CEnumeration( elabTypeSpec.getName() );
} else {
binding = new CStructure( elabTypeSpec ); binding = new CStructure( elabTypeSpec );
}
try { try {
((ICScope) binding.getScope()).addBinding( binding ); ((ICScope) binding.getScope()).addBinding( binding );
} catch ( DOMException e ) { } catch ( DOMException e ) {
}
} else {
if( binding instanceof CEnumeration ){
((CEnumeration)binding).addDeclaration( elabTypeSpec.getName() );
} }
} }
return binding; return binding;
@ -1242,10 +1267,17 @@ public class CVisitor {
} }
} else if( node instanceof IASTSimpleDeclaration && decl instanceof ICASTElaboratedTypeSpecifier){ } else if( node instanceof IASTSimpleDeclaration && decl instanceof ICASTElaboratedTypeSpecifier){
IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) node; IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) node;
if( simpleDecl.getDeclSpecifier() instanceof ICASTCompositeTypeSpecifier ){ IASTDeclSpecifier declSpec = simpleDecl.getDeclSpecifier();
ICASTCompositeTypeSpecifier compTypeSpec = (ICASTCompositeTypeSpecifier) simpleDecl.getDeclSpecifier(); IASTName name = null;
if( CharArrayUtils.equals( compTypeSpec.getName().toCharArray(), declName ) ){
return compTypeSpec; if( declSpec instanceof ICASTCompositeTypeSpecifier ){
name = ((ICASTCompositeTypeSpecifier)declSpec).getName();
} else if( declSpec instanceof ICASTEnumerationSpecifier ){
name = ((ICASTEnumerationSpecifier)declSpec).getName();
}
if( name != null ){
if( CharArrayUtils.equals( name.toCharArray(), declName ) ){
return declSpec;
} }
} }
} else if( node instanceof IASTSimpleDeclaration && decl instanceof IASTDeclarator ){ } else if( node instanceof IASTSimpleDeclaration && decl instanceof IASTDeclarator ){