diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 79a97b3c2e9..c21edd01ff2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -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 ); + } } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java index 10e40b2c122..f17e2029c14 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumeration.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java index 7f49efce031..10be3b84452 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CEnumerator.java @@ -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 ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index c2f4b3a3bf0..f1b76603bd1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -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 ){