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:
parent
b3ecffbb72
commit
04d743c153
4 changed files with 142 additions and 19 deletions
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ){
|
||||
|
|
|
@ -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 ){
|
||||
|
|
Loading…
Add table
Reference in a new issue