1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-07 09:46:02 +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.IParameter;
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.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
@ -2600,4 +2601,22 @@ public class AST2Tests extends AST2BaseTest {
assertEquals( ps.length, 1 );
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;
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.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
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.IType;
import org.eclipse.cdt.core.dom.ast.c.ICASTElaboratedTypeSpecifier;
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 {
private final ICASTEnumerationSpecifier enumSpec;
public CEnumeration( ICASTEnumerationSpecifier spec ){
spec = checkForDefinition( spec );
this.enumSpec = spec;
private IASTName [] declarations = null;
private IASTName definition = null;
public CEnumeration( IASTName enum ){
ASTNodeProperty prop = enum.getPropertyInParent();
if( prop == IASTElaboratedTypeSpecifier.TYPE_NAME )
declarations = new IASTName[] { enum };
else
definition = enum;
}
public IASTNode getPhysicalNode(){
return enumSpec;
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;
}
private ICASTEnumerationSpecifier checkForDefinition( ICASTEnumerationSpecifier spec ){
return spec;
public IASTNode getPhysicalNode(){
if( definition != null )
return definition;
return declarations[0];
}
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)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getName()
*/
public String getName() {
return enumSpec.getName().toString();
if( definition != null )
return definition.toString();
return declarations[0].toString();
}
public char[] getNameCharArray(){
return ((CASTName) enumSpec.getName()).toCharArray();
if( definition != null )
return definition.toCharArray();
return declarations[0].toCharArray();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/
public IScope getScope() {
return CVisitor.getContainingScope( enumSpec );
return CVisitor.getContainingScope( definition != null ? definition : declarations[0].getParent() );
}
public Object clone(){
@ -71,6 +118,13 @@ public class CEnumeration implements IEnumeration {
* @see org.eclipse.cdt.core.dom.ast.IEnumeration#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();
IEnumerator [] bindings = new IEnumerator [ enums.length ];
@ -79,4 +133,11 @@ public class CEnumeration implements IEnumeration {
}
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;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTNode;
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.IType;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
/**
* @author aniefer
*/
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;
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.parser.util.CharArrayUtils;
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;
/**
@ -502,11 +503,26 @@ public class CVisitor {
}
private static IBinding createBinding( ICASTEnumerationSpecifier enumeration ){
IEnumeration binding = new CEnumeration( enumeration );
try {
((ICScope)binding.getScope()).addBinding( binding );
IASTName name = enumeration.getName();
ICScope scope = (ICScope) getContainingScope( enumeration );
IBinding binding;
try {
binding = scope.getBinding( ICScope.NAMESPACE_TYPE_TAG, name.toCharArray() );
} 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;
}
private static IBinding createBinding( IASTEnumerator enumerator ){
@ -551,11 +567,20 @@ public class CVisitor {
//forward declaration
IBinding binding = resolveBinding( elabTypeSpec, CURRENT_SCOPE | TAGS );
if( binding == null ){
binding = new CStructure( elabTypeSpec );
if( elabTypeSpec.getKind() == IASTElaboratedTypeSpecifier.k_enum ){
binding = new CEnumeration( elabTypeSpec.getName() );
} else {
binding = new CStructure( elabTypeSpec );
}
try {
((ICScope) binding.getScope()).addBinding( binding );
} catch ( DOMException e ) {
}
} else {
if( binding instanceof CEnumeration ){
((CEnumeration)binding).addDeclaration( elabTypeSpec.getName() );
}
}
return binding;
}
@ -1242,10 +1267,17 @@ public class CVisitor {
}
} else if( node instanceof IASTSimpleDeclaration && decl instanceof ICASTElaboratedTypeSpecifier){
IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) node;
if( simpleDecl.getDeclSpecifier() instanceof ICASTCompositeTypeSpecifier ){
ICASTCompositeTypeSpecifier compTypeSpec = (ICASTCompositeTypeSpecifier) simpleDecl.getDeclSpecifier();
if( CharArrayUtils.equals( compTypeSpec.getName().toCharArray(), declName ) ){
return compTypeSpec;
IASTDeclSpecifier declSpec = simpleDecl.getDeclSpecifier();
IASTName name = null;
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 ){