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:
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.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 );
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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 IASTNode getPhysicalNode(){
|
public void addDeclaration( IASTName decl ){
|
||||||
return enumSpec;
|
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)
|
/* (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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ){
|
||||||
|
|
|
@ -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,11 +503,26 @@ public class CVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBinding createBinding( ICASTEnumerationSpecifier enumeration ){
|
private static IBinding createBinding( ICASTEnumerationSpecifier enumeration ){
|
||||||
IEnumeration binding = new CEnumeration( enumeration );
|
IASTName name = enumeration.getName();
|
||||||
try {
|
ICScope scope = (ICScope) getContainingScope( enumeration );
|
||||||
((ICScope)binding.getScope()).addBinding( binding );
|
IBinding binding;
|
||||||
|
try {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
private static IBinding createBinding( IASTEnumerator enumerator ){
|
private static IBinding createBinding( IASTEnumerator enumerator ){
|
||||||
|
@ -551,11 +567,20 @@ 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 ){
|
||||||
binding = new CStructure( elabTypeSpec );
|
if( elabTypeSpec.getKind() == IASTElaboratedTypeSpecifier.k_enum ){
|
||||||
|
binding = new CEnumeration( elabTypeSpec.getName() );
|
||||||
|
} else {
|
||||||
|
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 ){
|
||||||
|
|
Loading…
Add table
Reference in a new issue