1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 17:05:26 +02:00

class inheritance

This commit is contained in:
Andrew Niefer 2004-12-02 22:27:57 +00:00
parent cf4ba671c8
commit bb4f448825
5 changed files with 245 additions and 32 deletions

View file

@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.ParserLanguage;
/**
@ -240,5 +241,86 @@ public class AST2CPPTests extends AST2BaseTest {
assertSame( i1, i2 );
}
public void testBasicInheritance() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append( "class A { int i; }; \n" ); //$NON-NLS-1$
buffer.append( "class B : public A { void f(); }; \n" ); //$NON-NLS-1$
buffer.append( "void B::f() { i; } \n" ); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
IASTSimpleDeclaration decl = (IASTSimpleDeclaration) tu.getDeclarations()[0];
ICPPASTCompositeTypeSpecifier comp = (ICPPASTCompositeTypeSpecifier) decl.getDeclSpecifier();
IASTName name_A1 = comp.getName();
decl = (IASTSimpleDeclaration) comp.getMembers()[0];
IASTName name_i1 = decl.getDeclarators()[0].getName();
decl = (IASTSimpleDeclaration) tu.getDeclarations()[1];
comp = (ICPPASTCompositeTypeSpecifier) decl.getDeclSpecifier();
IASTName name_B1 = comp.getName();
ICPPASTBaseSpecifier base = comp.getBaseSpecifiers()[0];
IASTName name_A2 = base.getName();
decl = (IASTSimpleDeclaration) comp.getMembers()[0];
IASTName name_f1 = decl.getDeclarators()[0].getName();
IASTFunctionDefinition def = (IASTFunctionDefinition) tu.getDeclarations()[2];
ICPPASTQualifiedName name_f2 = (ICPPASTQualifiedName) def.getDeclarator().getName();
IASTName name_B2 = name_f2.getNames()[0];
IASTName name_f3 = name_f2.getNames()[1];
IASTCompoundStatement compound = (IASTCompoundStatement) def.getBody();
IASTExpressionStatement statement = (IASTExpressionStatement) compound.getStatements()[0];
IASTIdExpression idExp = (IASTIdExpression) statement.getExpression();
IASTName name_i2 = idExp.getName();
ICPPField i2 = (ICPPField) name_i2.resolveBinding();
ICPPField i1 = (ICPPField) name_i1.resolveBinding();
ICPPClassType A2 = (ICPPClassType) name_A2.resolveBinding();
ICPPClassType A1 = (ICPPClassType) name_A1.resolveBinding();
ICPPClassType B2 = (ICPPClassType) name_B2.resolveBinding();
ICPPClassType B1 = (ICPPClassType) name_B1.resolveBinding();
ICPPMethod f3 = (ICPPMethod) name_f3.resolveBinding();
ICPPMethod f2 = (ICPPMethod) name_f2.resolveBinding();
ICPPMethod f1 = (ICPPMethod) name_f1.resolveBinding();
assertNotNull( A1 );
assertNotNull( B1 );
assertNotNull( i1 );
assertNotNull( f1 );
assertSame( A1, A2 );
assertSame( B1, B2 );
assertSame( i1, i2 );
assertSame( f1, f2 );
assertSame( f2, f3 );
}
// public void testNamespaces() throws Exception {
// StringBuffer buffer = new StringBuffer();
// buffer.append( "namespace A{ \n"); //$NON-NLS-1$
// buffer.append( " int a; \n"); //$NON-NLS-1$
// buffer.append( "} \n"); //$NON-NLS-1$
// buffer.append( "namespace B{ \n"); //$NON-NLS-1$
// buffer.append( " using namespace A; \n"); //$NON-NLS-1$
// buffer.append( "} \n"); //$NON-NLS-1$
// buffer.append( "namespace C{ \n"); //$NON-NLS-1$
// buffer.append( " using namespace A; \n"); //$NON-NLS-1$
// buffer.append( "} \n"); //$NON-NLS-1$
// buffer.append( " \n"); //$NON-NLS-1$
// buffer.append( "namespace BC{ \n"); //$NON-NLS-1$
// buffer.append( " using namespace B; \n"); //$NON-NLS-1$
// buffer.append( " using namespace C; \n"); //$NON-NLS-1$
// buffer.append( "} \n"); //$NON-NLS-1$
// buffer.append( " \n"); //$NON-NLS-1$
// buffer.append( "void f(){ \n"); //$NON-NLS-1$
// buffer.append( " BC::a++; //ok \n"); //$NON-NLS-1$
// buffer.append( "} \n"); //$NON-NLS-1$
//
// IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
//
// //CPPVisitor.visitTranslationUnit( tu )
// }
}

View file

@ -10,8 +10,6 @@
**********************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName;
@ -31,6 +29,8 @@ public interface ICPPASTCompositeTypeSpecifier extends IASTCompositeTypeSpecifie
public static interface ICPPASTBaseSpecifier extends IASTNode
{
public static final ICPPASTBaseSpecifier[] EMPTY_BASESPECIFIER_ARRAY = new ICPPASTBaseSpecifier[0];
public boolean isVirtual();
public void setVirtual( boolean value );
@ -46,7 +46,7 @@ public interface ICPPASTCompositeTypeSpecifier extends IASTCompositeTypeSpecifie
public void setName( IASTName name );
}
public List getBaseSpecifiers();
public ICPPASTBaseSpecifier[] getBaseSpecifiers();
public void addBaseSpecifier( ICPPASTBaseSpecifier baseSpec );
}

View file

@ -10,10 +10,6 @@
**********************************************************************/
package org.eclipse.cdt.internal.core.parser2.cpp;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IScope;
@ -32,10 +28,10 @@ public class CPPASTCompositeTypeSpecifier extends CPPASTBaseDeclSpecifier
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier#getBaseSpecifiers()
*/
public List getBaseSpecifiers() {
if( baseSpecs == null ) return Collections.EMPTY_LIST;
public ICPPASTBaseSpecifier[] getBaseSpecifiers() {
if( baseSpecs == null ) return ICPPASTBaseSpecifier.EMPTY_BASESPECIFIER_ARRAY;
removeNullBaseSpecs();
return Arrays.asList( baseSpecs );
return baseSpecs;
}
/* (non-Javadoc)

View file

@ -109,8 +109,33 @@ public class CPPASTQualifiedName extends CPPASTNode implements ICPPASTQualifiedN
* @see org.eclipse.cdt.core.dom.ast.IASTName#toCharArray()
*/
public char[] toCharArray() {
// TODO Auto-generated method stub
return null;
if( names == null ) return null;
removeNullNames();
//count first
int len = 0;
for( int i = 0; i < names.length; ++i )
{
char [] n = names[i].toCharArray();
if( n == null )
return null;
len += n.length;
if( i != names.length - 1 )
len += 2;
}
char [] nameArray = new char[ len ];
int pos = 0;
for( int i = 0; i < names.length; i++ ){
char [] n = names[i].toCharArray();
System.arraycopy( n, 0, nameArray, pos, n.length );
pos += n.length;
if( i != names.length - 1 ){
nameArray[pos++] = ':';
nameArray[pos++] = ':';
}
}
return nameArray;
}

View file

@ -52,10 +52,12 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.parser2.c.CASTFunctionDeclarator;
import org.eclipse.cdt.internal.core.parser.pst.ISymbol;
import org.eclipse.cdt.internal.core.parser.pst.ITypeInfo;
/**
* @author aniefer
@ -68,7 +70,8 @@ public class CPPVisitor {
public static IBinding createBinding(IASTName name) {
IASTNode parent = name.getParent();
if( parent instanceof IASTNamedTypeSpecifier ||
parent instanceof ICPPASTQualifiedName )
parent instanceof ICPPASTQualifiedName ||
parent instanceof ICPPASTBaseSpecifier )
{
return resolveBinding( name );
} else if( parent instanceof IASTIdExpression ){
@ -134,6 +137,8 @@ public class CPPVisitor {
}
public static IScope getContainingScope( IASTNode node ){
if( node == null )
return null;
if( node instanceof IASTName )
return getContainingScope( (IASTName) node );
else if( node instanceof IASTDeclaration )
@ -323,6 +328,8 @@ public class CPPVisitor {
}
} else if( parent instanceof IASTDeclarator ){
data.forDefinition = true;
} else if ( parent instanceof ICPPASTBaseSpecifier ) {
//filter out non-type names
}
return data;
}
@ -379,10 +386,14 @@ public class CPPVisitor {
}
} else if( declaration instanceof IASTFunctionDefinition ){
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
CASTFunctionDeclarator declarator = (CASTFunctionDeclarator) functionDef.getDeclarator();
IASTFunctionDeclarator declarator = functionDef.getDeclarator();
//check the function itself
IASTName declName = declarator.getName();
if( declName instanceof ICPPASTQualifiedName ){
IASTName [] names = ((ICPPASTQualifiedName)declName).getNames();
declName = names[ names.length - 1 ];
}
if( CharArrayUtils.equals( declName.toCharArray(), data.name ) ){
return declName;
}
@ -408,8 +419,11 @@ public class CPPVisitor {
while( scope != null ){
IASTNode blockItem = getContainingBlockItem( node );
List directives = null;
if( !data.usingDirectivesOnly )
directives = lookupInScope( data, scope, blockItem );
if( !data.usingDirectivesOnly ){
directives = new ArrayList(2);
data.foundItems = lookupInScope( data, scope, blockItem, directives );
}
if( !data.ignoreUsingDirectives ) {
data.visited.clear();
@ -434,7 +448,7 @@ public class CPPVisitor {
return;
if( !data.usingDirectivesOnly && scope instanceof ICPPClassScope ){
//TODO : lookupInParents
data.foundItems = lookupInParents( data, (ICPPClassScope) scope );
}
if( data.foundItems != null && !data.foundItems.isEmpty() )
@ -443,11 +457,104 @@ public class CPPVisitor {
//if still not found, loop and check our containing scope
if( data.qualified && !data.usingDirectives.isEmpty() )
data.usingDirectivesOnly = true;
node = blockItem.getParent();
if( blockItem != null )
node = blockItem.getParent();
scope = (ICPPScope) scope.getParent();
}
}
private static List lookupInParents( LookupData data, ICPPClassScope lookIn ){
ICPPASTCompositeTypeSpecifier compositeTypeSpec = (ICPPASTCompositeTypeSpecifier) lookIn.getPhysicalNode();
ICPPASTBaseSpecifier [] bases = compositeTypeSpec.getBaseSpecifiers();
List inherited = null;
List result = null;
if( bases.length == 0 )
return null;
//use data to detect circular inheritance
if( data.inheritanceChain == null )
data.inheritanceChain = new ObjectSet( 2 );
data.inheritanceChain.put( lookIn );
int size = bases.length;
for( int i = 0; i < size; i++ )
{
ICPPClassType binding = (ICPPClassType) bases[i].getName().resolveBinding();
ICPPClassScope parent = (ICPPClassScope) binding.getCompositeScope();
if( parent == null )
continue;
if( !bases[i].isVirtual() || !data.visited.containsKey( parent ) ){
if( bases[i].isVirtual() ){
if( data.visited == ObjectSet.EMPTY_SET )
data.visited = new ObjectSet(2);
data.visited.put( parent );
}
//if the inheritanceChain already contains the parent, then that
//is circular inheritance
if( ! data.inheritanceChain.containsKey( parent ) ){
//is this name define in this scope?
inherited = lookupInScope( data, parent, null, null );
if( inherited == null || inherited.isEmpty() ){
inherited = lookupInParents( data, parent );
}
} else {
//throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance );
}
}
if( inherited != null && !inherited.isEmpty() ){
if( result == null || result.isEmpty() ){
result = inherited;
} else if ( inherited != null && !inherited.isEmpty() ) {
for( int j = 0; j < result.size(); j++ ) {
IASTName n = (IASTName) result.get(j);
if( !checkAmbiguity( n, inherited ) ){
//throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
return null;
}
}
}
} else {
inherited = null; //reset temp for next iteration
}
}
data.inheritanceChain.remove( lookIn );
return result;
}
private static boolean checkAmbiguity( Object obj1, Object obj2 ){
//it is not ambiguous if they are the same thing and it is static or an enumerator
if( obj1 == obj2 ){
List objList = ( obj1 instanceof List ) ? (List) obj1 : null;
int objListSize = ( objList != null ) ? objList.size() : 0;
ISymbol symbol = ( objList != null ) ? (ISymbol) objList.get(0) : ( ISymbol )obj1;
int idx = 1;
while( symbol != null ) {
ITypeInfo type = ((ISymbol)obj1).getTypeInfo();
if( !type.checkBit( ITypeInfo.isStatic ) && !type.isType( ITypeInfo.t_enumerator ) ){
return false;
}
if( objList != null && idx < objListSize ){
symbol = (ISymbol) objList.get( idx++ );
} else {
symbol = null;
}
}
return true;
}
return false;
}
static private void processDirectives( LookupData data, IScope scope, List directives ){
if( directives == null || directives.size() == 0 )
return;
@ -503,12 +610,12 @@ public class CPPVisitor {
* @param scope
* @return List of encountered using directives
*/
static private List lookupInScope( LookupData data, ICPPScope scope, IASTNode blockItem ) {
static private List lookupInScope( LookupData data, ICPPScope scope, IASTNode blockItem, List usingDirectives ) {
IASTName possible = null;
IASTNode [] nodes = null;
IASTNode parent = scope.getPhysicalNode();
List usingDirectives = null;
List found = null;
if( parent instanceof IASTCompoundStatement ){
IASTCompoundStatement compound = (IASTCompoundStatement) parent;
@ -529,16 +636,15 @@ public class CPPVisitor {
break;
if( item instanceof ICPPASTUsingDirective && !data.ignoreUsingDirectives ) {
if( usingDirectives == null )
usingDirectives = new ArrayList(2);
usingDirectives.add( item );
if( usingDirectives != null )
usingDirectives.add( item );
continue;
}
possible = collectResult( data, item, (item == parent) );
if( possible != null ){
if( data.foundItems == null )
data.foundItems = new ArrayList(2);
data.foundItems.add( possible );
if( found == null )
found = new ArrayList(2);
found.add( possible );
}
if( idx > -1 && ++idx < nodes.length ){
item = nodes[idx];
@ -546,7 +652,7 @@ public class CPPVisitor {
item = null;
}
}
return usingDirectives;
return found;
}
static private List lookupInNominated( LookupData data, ICPPScope scope, List transitives ){
@ -567,13 +673,17 @@ public class CPPVisitor {
data.visited = new ObjectSet(2);
}
data.visited.put( temp );
int pre = ( data.foundItems != null ) ? 0 : data.foundItems.size();
List usings = lookupInScope( data, scope, null );
int post = ( data.foundItems != null ) ? 0 : data.foundItems.size();
List usings = new ArrayList(2);
List found = lookupInScope( data, scope, null, usings );
if( data.foundItems == null )
data.foundItems = found;
else if( found != null )
data.foundItems.addAll( found );
//only consider the transitive using directives if we are an unqualified
//lookup, or we didn't find the name in decl
if( usings != null && usings.size() > 0 && (!data.qualified || (pre == post)) ){
if( usings != null && usings.size() > 0 && (!data.qualified || found == null ) ){
transitives.addAll( usings );
}
}