1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-26 02:15:31 +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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; 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.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserLanguage;
/** /**
@ -240,5 +241,86 @@ public class AST2CPPTests extends AST2BaseTest {
assertSame( i1, i2 ); 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; 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.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName; 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 interface ICPPASTBaseSpecifier extends IASTNode
{ {
public static final ICPPASTBaseSpecifier[] EMPTY_BASESPECIFIER_ARRAY = new ICPPASTBaseSpecifier[0];
public boolean isVirtual(); public boolean isVirtual();
public void setVirtual( boolean value ); public void setVirtual( boolean value );
@ -46,7 +46,7 @@ public interface ICPPASTCompositeTypeSpecifier extends IASTCompositeTypeSpecifie
public void setName( IASTName name ); public void setName( IASTName name );
} }
public List getBaseSpecifiers(); public ICPPASTBaseSpecifier[] getBaseSpecifiers();
public void addBaseSpecifier( ICPPASTBaseSpecifier baseSpec ); public void addBaseSpecifier( ICPPASTBaseSpecifier baseSpec );
} }

View file

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

View file

@ -109,8 +109,33 @@ public class CPPASTQualifiedName extends CPPASTNode implements ICPPASTQualifiedN
* @see org.eclipse.cdt.core.dom.ast.IASTName#toCharArray() * @see org.eclipse.cdt.core.dom.ast.IASTName#toCharArray()
*/ */
public char[] toCharArray() { public char[] toCharArray() {
// TODO Auto-generated method stub if( names == null ) return 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.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; 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.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.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectMap; import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.core.parser.util.ObjectSet; 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 * @author aniefer
@ -68,7 +70,8 @@ public class CPPVisitor {
public static IBinding createBinding(IASTName name) { public static IBinding createBinding(IASTName name) {
IASTNode parent = name.getParent(); IASTNode parent = name.getParent();
if( parent instanceof IASTNamedTypeSpecifier || if( parent instanceof IASTNamedTypeSpecifier ||
parent instanceof ICPPASTQualifiedName ) parent instanceof ICPPASTQualifiedName ||
parent instanceof ICPPASTBaseSpecifier )
{ {
return resolveBinding( name ); return resolveBinding( name );
} else if( parent instanceof IASTIdExpression ){ } else if( parent instanceof IASTIdExpression ){
@ -134,6 +137,8 @@ public class CPPVisitor {
} }
public static IScope getContainingScope( IASTNode node ){ public static IScope getContainingScope( IASTNode node ){
if( node == null )
return null;
if( node instanceof IASTName ) if( node instanceof IASTName )
return getContainingScope( (IASTName) node ); return getContainingScope( (IASTName) node );
else if( node instanceof IASTDeclaration ) else if( node instanceof IASTDeclaration )
@ -323,6 +328,8 @@ public class CPPVisitor {
} }
} else if( parent instanceof IASTDeclarator ){ } else if( parent instanceof IASTDeclarator ){
data.forDefinition = true; data.forDefinition = true;
} else if ( parent instanceof ICPPASTBaseSpecifier ) {
//filter out non-type names
} }
return data; return data;
} }
@ -379,10 +386,14 @@ public class CPPVisitor {
} }
} else if( declaration instanceof IASTFunctionDefinition ){ } else if( declaration instanceof IASTFunctionDefinition ){
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration; IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
CASTFunctionDeclarator declarator = (CASTFunctionDeclarator) functionDef.getDeclarator(); IASTFunctionDeclarator declarator = functionDef.getDeclarator();
//check the function itself //check the function itself
IASTName declName = declarator.getName(); 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 ) ){ if( CharArrayUtils.equals( declName.toCharArray(), data.name ) ){
return declName; return declName;
} }
@ -408,8 +419,11 @@ public class CPPVisitor {
while( scope != null ){ while( scope != null ){
IASTNode blockItem = getContainingBlockItem( node ); IASTNode blockItem = getContainingBlockItem( node );
List directives = null; List directives = null;
if( !data.usingDirectivesOnly ) if( !data.usingDirectivesOnly ){
directives = lookupInScope( data, scope, blockItem ); directives = new ArrayList(2);
data.foundItems = lookupInScope( data, scope, blockItem, directives );
}
if( !data.ignoreUsingDirectives ) { if( !data.ignoreUsingDirectives ) {
data.visited.clear(); data.visited.clear();
@ -434,7 +448,7 @@ public class CPPVisitor {
return; return;
if( !data.usingDirectivesOnly && scope instanceof ICPPClassScope ){ if( !data.usingDirectivesOnly && scope instanceof ICPPClassScope ){
//TODO : lookupInParents data.foundItems = lookupInParents( data, (ICPPClassScope) scope );
} }
if( data.foundItems != null && !data.foundItems.isEmpty() ) 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 still not found, loop and check our containing scope
if( data.qualified && !data.usingDirectives.isEmpty() ) if( data.qualified && !data.usingDirectives.isEmpty() )
data.usingDirectivesOnly = true; data.usingDirectivesOnly = true;
node = blockItem.getParent();
if( blockItem != null )
node = blockItem.getParent();
scope = (ICPPScope) scope.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 ){ static private void processDirectives( LookupData data, IScope scope, List directives ){
if( directives == null || directives.size() == 0 ) if( directives == null || directives.size() == 0 )
return; return;
@ -503,12 +610,12 @@ public class CPPVisitor {
* @param scope * @param scope
* @return List of encountered using directives * @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; IASTName possible = null;
IASTNode [] nodes = null; IASTNode [] nodes = null;
IASTNode parent = scope.getPhysicalNode(); IASTNode parent = scope.getPhysicalNode();
List usingDirectives = null; List found = null;
if( parent instanceof IASTCompoundStatement ){ if( parent instanceof IASTCompoundStatement ){
IASTCompoundStatement compound = (IASTCompoundStatement) parent; IASTCompoundStatement compound = (IASTCompoundStatement) parent;
@ -529,16 +636,15 @@ public class CPPVisitor {
break; break;
if( item instanceof ICPPASTUsingDirective && !data.ignoreUsingDirectives ) { if( item instanceof ICPPASTUsingDirective && !data.ignoreUsingDirectives ) {
if( usingDirectives == null ) if( usingDirectives != null )
usingDirectives = new ArrayList(2); usingDirectives.add( item );
usingDirectives.add( item );
continue; continue;
} }
possible = collectResult( data, item, (item == parent) ); possible = collectResult( data, item, (item == parent) );
if( possible != null ){ if( possible != null ){
if( data.foundItems == null ) if( found == null )
data.foundItems = new ArrayList(2); found = new ArrayList(2);
data.foundItems.add( possible ); found.add( possible );
} }
if( idx > -1 && ++idx < nodes.length ){ if( idx > -1 && ++idx < nodes.length ){
item = nodes[idx]; item = nodes[idx];
@ -546,7 +652,7 @@ public class CPPVisitor {
item = null; item = null;
} }
} }
return usingDirectives; return found;
} }
static private List lookupInNominated( LookupData data, ICPPScope scope, List transitives ){ static private List lookupInNominated( LookupData data, ICPPScope scope, List transitives ){
@ -567,13 +673,17 @@ public class CPPVisitor {
data.visited = new ObjectSet(2); data.visited = new ObjectSet(2);
} }
data.visited.put( temp ); data.visited.put( temp );
int pre = ( data.foundItems != null ) ? 0 : data.foundItems.size(); List usings = new ArrayList(2);
List usings = lookupInScope( data, scope, null ); List found = lookupInScope( data, scope, null, usings );
int post = ( data.foundItems != null ) ? 0 : data.foundItems.size(); 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 //only consider the transitive using directives if we are an unqualified
//lookup, or we didn't find the name in decl //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 ); transitives.addAll( usings );
} }
} }