1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 14:42:11 +02:00

Change scope caching to improve performance

This commit is contained in:
Andrew Niefer 2005-03-03 19:28:53 +00:00
parent b733817bab
commit 1741ff8c15
10 changed files with 419 additions and 356 deletions

View file

@ -13,12 +13,28 @@
*/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTNode;
/**
* @author aniefer
*/
public interface ICPPNamespaceScope extends ICPPScope {
boolean isFullyResolved( IASTName name );
/**
* Add an IASTNode that nominates another namespace to this scope
* Most commonly, ICPPASTUsingDirectives, but in the case of unnamed namespaces,
* it could be an ICPPASTNamespaceDefinition
* @param directive
*/
public void addUsingDirective( IASTNode directive ) throws DOMException;
/**
* Get the IASTNodes that have been added to this scope to nominate other
* namespaces during lookup. (ICPPASTUsingDirective or ICPPASTNamespaceDefinition)
* @return
*/
public IASTNode[] getUsingDirectives() throws DOMException;
}

View file

@ -19,10 +19,43 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
/**
* The ICPPScope serves as a mechanism for caching IASTNames and
* bindings to speed up resolution.
*
* @author aniefer
*/
public interface ICPPScope extends IScope {
public void addBinding( IBinding binding ) throws DOMException;
public IBinding getBinding( IASTName name ) throws DOMException;
/**
* Add an IASTName to be cached in this scope
* @param name
* @throws DOMException
*/
public void addName( IASTName name ) throws DOMException;
/**
* Get the binding that the given name would resolve to in this scope.
* Could return null if there is no matching binding in this scope,
* or if resolve == false and the appropriate binding has not yet been
* resolved.
*
* @param name
* @param resolve : whether or not to resolve the matching binding if it
* has not been so already.
* @return : the binding in this scope that matches the name, or null
* @throws DOMException
*/
public IBinding getBinding( IASTName name, boolean resolve ) throws DOMException;
/**
* Set whether or not all the names in this scope have been cached
* @param b
*/
public void setFullyCached(boolean b) throws DOMException;
/**
* whether or not this scope's cache contains all the names
* @return
*/
public boolean isFullyCached() throws DOMException;
}

View file

@ -39,6 +39,8 @@ public class ArrayUtil {
* @return
*/
static public Object [] append( Class c, Object[] array, Object obj ){
if( obj == null )
return array;
if( array == null || array.length == 0){
array = (Object[]) Array.newInstance( c, DEFAULT_LENGTH );
array[0] = obj;

View file

@ -16,7 +16,6 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
/**
* @author jcamelon
@ -111,7 +110,7 @@ public class CPPASTTemplateId extends CPPASTNode implements ICPPASTTemplateId {
*/
public IBinding resolveBinding() {
// TODO templates not yet supported
return new ProblemBinding( -1, templateName.toCharArray() );
return new CPPScope.CPPTemplateProblem( -1, templateName.toCharArray() );
}
public IBinding[] resolvePrefix() {

View file

@ -15,6 +15,7 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
@ -32,15 +33,13 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPSemantics.LookupData;
/**
* @author aniefer
*/
public class CPPClassScope extends CPPScope implements ICPPClassScope {
private CharArrayObjectMap bindings = CharArrayObjectMap.EMPTY_MAP;
private ICPPConstructor [] constructors = null;
boolean checkForAdditionalBindings = true;
private ObjectSet constructorBindings = ObjectSet.EMPTY_SET;
private ObjectSet constructorNames = ObjectSet.EMPTY_SET;
public CPPClassScope( ICPPASTCompositeTypeSpecifier physicalNode ) {
super( physicalNode );
@ -61,15 +60,22 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
return;
}
char [] className = compTypeSpec.getName().toCharArray();
IASTName name = compTypeSpec.getName();
if( name instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName) name).getNames();
name = ns[ ns.length - 1 ];
}
checkForAdditionalBindings = false;
IBinding binding = compTypeSpec.getName().resolveBinding();
if( !(binding instanceof ICPPClassType ) )
return;
ICPPClassType clsType = (ICPPClassType) binding;
char [] className = name.toCharArray();
//default constructor: A()
addBinding( new CPPImplicitConstructor( this, className, IParameter.EMPTY_PARAMETER_ARRAY ) );
ICPPClassType clsType = (ICPPClassType) compTypeSpec.getName().resolveBinding();
//copy constructor: A( const A & )
IType pType = new CPPReferenceType( new CPPQualifierType( clsType, true, false ) );
IParameter [] ps = new IParameter [] { new CPPParameter( pType ) };
@ -82,8 +88,6 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
//destructor: ~A()
char [] dtorName = CharArrayUtils.concat( "~".toCharArray(), className ); //$NON-NLS-1$
addBinding( new CPPImplicitMethod( this, dtorName, new CPPBasicType( IBasicType.t_unspecified, 0 ), IParameter.EMPTY_PARAMETER_ARRAY ) );
checkForAdditionalBindings = true;
}
/* (non-Javadoc)
@ -91,99 +95,82 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
*/
public void addBinding(IBinding binding) {
if( binding instanceof ICPPConstructor ){
addConstructor( (ICPPConstructor) binding );
addConstructor( binding );
return;
}
if( bindings == CharArrayObjectMap.EMPTY_MAP )
if( bindings == null )
bindings = new CharArrayObjectMap(1);
char [] c = binding.getNameCharArray();
Object o = bindings.get( c );
if( o != null ){
if( o instanceof IBinding[] ){
bindings.put( c, ArrayUtil.append( IBinding.class, (Object[]) o, binding ) );
if( o instanceof Object[] ){
bindings.put( c, ArrayUtil.append( Object.class, (Object[]) o, binding ) );
} else {
bindings.put( c, new IBinding[] { (IBinding) o, binding } );
bindings.put( c, new Object[] { o, binding } );
}
} else {
bindings.put( c, binding );
if( checkForAdditionalBindings ){
//need to ensure we have all bindings that correspond to this char[]
checkForAdditionalBindings = false;
LookupData data = new LookupData( c );
try {
data.foundItems = CPPSemantics.lookupInScope( data, this, null, null );
} catch ( DOMException e ) {
}
if( data.foundItems != null ){
IASTName [] ns = (IASTName[]) data.foundItems;
for( int i = 0; i < ns.length && ns[i] != null; i++ ){
ns[i].resolveBinding();
}
}
checkForAdditionalBindings = true;
}
}
}
private void addConstructor( ICPPConstructor constructor ){
if( constructors == null )
constructors = new ICPPConstructor[ 2 ];
int i = 0;
for( ; i < constructors.length; i++ ){
if( constructors[i] == null ){
constructors[i] = constructor;
return;
}
}
ICPPConstructor [] temp = new ICPPConstructor[ constructors.length * 2 ];
System.arraycopy( constructors, 0, temp, 0, constructors.length );
temp[ constructors.length ] = constructor;
constructors = temp;
public void addName(IASTName name) {
IASTNode parent = name.getParent();
if( parent instanceof IASTDeclarator ){
if( CPPVisitor.isConstructor( this, (IASTDeclarator) parent ) ){
addConstructor( name );
return;
}
}
super.addName( name );
}
private void addConstructor( Object constructor ){
if( constructor instanceof IBinding ){
if( constructorBindings == ObjectSet.EMPTY_SET )
constructorBindings = new ObjectSet( 2 );
constructorBindings.put( constructor );
} else {
if( constructorNames == ObjectSet.EMPTY_SET )
constructorNames = new ObjectSet( 2 );
constructorNames.put( constructor );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#getBinding(int, char[])
*/
public IBinding getBinding( IASTName name ) throws DOMException {
public IBinding getBinding( IASTName name, boolean resolve ) throws DOMException {
char [] c = name.toCharArray();
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
if( CharArrayUtils.equals( c, compType.getName().toCharArray() ) ){
IASTName compName = compType.getName();
if( compName instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)compName).getNames();
compName = ns[ ns.length - 1 ];
}
if( CharArrayUtils.equals( c, compName.toCharArray() ) ){
if( isConstructorReference( name ) ){
if( constructors == null )
return null;
return CPPSemantics.resolveAmbiguities( name, constructors );
// if( constructors == null )
// return null;
return CPPSemantics.resolveAmbiguities( name, getConstructors( resolve ) );
}
//9.2 ... The class-name is also inserted into the scope of the class itself
return compType.getName().resolveBinding();
}
Object obj = bindings.get( c );
if( obj != null ){
if( obj instanceof IBinding[] ){
obj = CPPSemantics.resolveAmbiguities( name, (IBinding[]) obj );
}
}
return (IBinding) obj;
return super.getBinding( name, resolve );
}
protected ICPPConstructor [] getConstructors(){
if( constructors == null ){
constructors = new ICPPConstructor[0];
return constructors;
}
int i = 0;
for( ; i < constructors.length; i++ )
if( constructors[i] == null )
break;
if( i < constructors.length ){
ICPPConstructor[] temp = new ICPPConstructor[ i ];
System.arraycopy( constructors, 0, temp, 0, i );
constructors = temp;
}
return constructors;
protected ICPPConstructor [] getConstructors( boolean forceResolve ){
if( forceResolve && constructorNames.size() > 0 ){
Object [] names = constructorNames.keyArray();
for( int i = 0; i < names.length; i++ ){
ICPPConstructor ctor = (ICPPConstructor) ((IASTName)names[i]).resolveBinding();
constructorBindings.put( ctor );
}
constructorNames.clear();
}
return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, constructorBindings.keyArray(), true);
}
/* (non-Javadoc)
@ -193,30 +180,9 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
char [] n = name.toCharArray();
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
if( CharArrayUtils.equals( n, compType.getName().toCharArray() ) ){
return (IBinding[]) ArrayUtil.addAll( IBinding.class, null, getConstructors() );
return (IBinding[]) ArrayUtil.addAll( IBinding.class, null, getConstructors( true ) );
}
if( bindings != null && bindings.containsKey( n ) ){
Object o = bindings.get( n );
if( o instanceof IBinding[] )
return (IBinding[]) ArrayUtil.trim( IBinding.class, (Object[]) o );
return new IBinding[] { (IBinding) o };
}
LookupData data = new LookupData( n );
try {
data.foundItems = CPPSemantics.lookupInScope( data, this, null, null );
} catch ( DOMException e ) {
}
if( data.foundItems != null ){
IASTName [] ns = (IASTName[]) data.foundItems;
ObjectSet set = new ObjectSet( ns.length );
for( int i = 0; i < ns.length && ns[i] != null; i++ ){
set.put( ns[i].resolveBinding() );
}
return (IBinding[]) ArrayUtil.trim( IBinding.class, set.keyArray(), true );
}
return new IBinding[0];
return super.find( name );
}
private boolean isConstructorReference( IASTName name ){

View file

@ -388,7 +388,7 @@ public class CPPClassType implements ICPPClassType, ICPPBinding {
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getConstructors()
*/
public ICPPConstructor[] getConstructors() {
public ICPPConstructor[] getConstructors() throws DOMException {
if( definition == null ){
checkForDefinition();
if( definition == null ){
@ -397,23 +397,24 @@ public class CPPClassType implements ICPPClassType, ICPPBinding {
}
ICPPClassScope scope = (ICPPClassScope) getCompositeScope();
if( scope.isFullyCached() )
return ((CPPClassScope)scope).getConstructors( true );
IASTDeclaration [] members = getCompositeTypeSpecifier().getMembers();
for( int i = 0; i < members.length; i++ ){
if( members[i] instanceof IASTSimpleDeclaration ){
IASTDeclarator [] dtors = ((IASTSimpleDeclaration)members[i]).getDeclarators();
for( int j = 0; j < dtors.length; j++ ){
if( dtors[j] == null ) break;
if( CPPVisitor.isConstructor( scope, dtors[j] ) )
dtors[j].getName().resolveBinding();
scope.addName( dtors[j].getName() );
}
} else if( members[i] instanceof IASTFunctionDefinition ){
IASTDeclarator dtor = ((IASTFunctionDefinition)members[i]).getDeclarator();
if( CPPVisitor.isConstructor( scope, dtor ) )
dtor.getName().resolveBinding();
scope.addName( dtor.getName() );
}
}
return ((CPPClassScope)scope).getConstructors();
return ((CPPClassScope)scope).getConstructors( true );
}
/* (non-Javadoc)

View file

@ -13,122 +13,30 @@
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPSemantics.LookupData;
/**
* @author aniefer
*/
public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{
private static class ScopeMap extends CharArrayObjectMap {
private boolean[] resolvedTable;
public ScopeMap( int initialSize ) {
super( initialSize );
resolvedTable = new boolean[capacity()];
}
protected void resize(int size) {
boolean[] oldResolvedTable = resolvedTable;
resolvedTable = new boolean[size];
System.arraycopy(oldResolvedTable, 0, resolvedTable, 0, oldResolvedTable.length);
super.resize(size);
}
public boolean isFullyResolved( char [] name ){
int i = lookup(name, 0, name.length);
if( i >= 0 )
return resolvedTable[i];
return false;
}
public void setFullyResolved( char [] name ){
int i = lookup(name, 0, name.length);
if( i >= 0 )
resolvedTable[i] = true;
}
}
private ScopeMap bindings = null;
IASTNode[] usings = null;
public CPPNamespaceScope( IASTNode physicalNode ) {
public CPPNamespaceScope( IASTNode physicalNode ) {
super( physicalNode );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#addBinding(org.eclipse.cdt.core.dom.ast.IBinding)
*/
public void addBinding(IBinding binding) {
if( bindings == null )
bindings = new ScopeMap(1);
char [] c = binding.getNameCharArray();
Object o = bindings.get( c );
if( o != null ){
if( o instanceof IBinding[] ){
bindings.put( c, ArrayUtil.append( IBinding.class, (Object[]) o, binding ) );
} else {
bindings.put( c, new IBinding[] { (IBinding) o, binding } );
}
} else {
bindings.put( c, binding );
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#getBinding(int, char[])
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope#getUsingDirectives()
*/
public IBinding getBinding( IASTName name ) {
char [] c = name.toCharArray();
if( bindings == null )
return null;
Object obj = bindings.get( c );
if( obj != null ){
if( obj instanceof IBinding[] ){
obj = CPPSemantics.resolveAmbiguities( name, (IBinding[]) obj );
}
}
return (IBinding) obj;
public IASTNode[] getUsingDirectives() {
return (IASTNode[]) ArrayUtil.trim( IASTNode.class, usings, true );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope#addUsingDirective(org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDirective)
*/
public IBinding[] find(String name) {
char [] n = name.toCharArray();
if( bindings != null && bindings.isFullyResolved( n ) ){
Object o = bindings.get( n );
if( o instanceof IBinding[] )
return (IBinding[]) ArrayUtil.trim( IBinding.class, (Object[]) o );
return new IBinding[] { (IBinding) o };
}
LookupData data = new LookupData( n );
try {
data.foundItems = CPPSemantics.lookupInScope( data, this, null, null );
} catch ( DOMException e ) {
}
if( data.foundItems != null ){
IASTName [] ns = (IASTName[]) data.foundItems;
ObjectSet set = new ObjectSet( ns.length );
for( int i = 0; i < ns.length && ns[i] != null; i++ ){
set.put( ns[i].resolveBinding() );
}
return (IBinding[]) ArrayUtil.trim( IBinding.class, set.keyArray(), true );
}
return new IBinding[0];
}
public void setFullyResolved( IASTName name ){
if( bindings != null )
bindings.setFullyResolved( name.toCharArray() );
}
public boolean isFullyResolved( IASTName name ){
if( bindings != null )
return bindings.isFullyResolved( name.toCharArray() );
return false;
public void addUsingDirective(IASTNode directive) {
usings = (IASTNode[]) ArrayUtil.append( IASTNode.class, usings, directive );
}
}

View file

@ -18,8 +18,14 @@ import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPCompositeBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPSemantics.LookupData;
/**
* @author aniefer
@ -29,11 +35,11 @@ abstract public class CPPScope implements ICPPScope{
public CPPScopeProblem( int id, char[] arg ) {
super( id, arg );
}
public void addBinding( IBinding binding ) throws DOMException {
public void addName( IASTName name ) throws DOMException {
throw new DOMException( this );
}
public IBinding getBinding( IASTName name ) throws DOMException {
public IBinding getBinding( IASTName name, boolean resolve ) throws DOMException {
throw new DOMException( this );
}
@ -44,6 +50,16 @@ abstract public class CPPScope implements ICPPScope{
public IBinding[] find( String name ) throws DOMException {
throw new DOMException( this );
}
public void setFullyCached(boolean b) {
}
public boolean isFullyCached() {
return false;
}
}
public static class CPPTemplateProblem extends CPPScopeProblem {
public CPPTemplateProblem(int id, char[] arg) {
super(id, arg);
}
}
@ -62,4 +78,113 @@ abstract public class CPPScope implements ICPPScope{
public IASTNode getPhysicalNode() throws DOMException{
return physicalNode;
}
protected CharArrayObjectMap bindings = null;
public void addName(IASTName name) {
if( bindings == null )
bindings = new CharArrayObjectMap(1);
char [] c = name.toCharArray();
Object o = bindings.get( c );
if( o != null ){
if( o instanceof ObjectSet ){
((ObjectSet)o).put( name );
//bindings.put( c, ArrayUtil.append( Object.class, (Object[]) o, name ) );
} else {
ObjectSet temp = new ObjectSet( 2 );
temp.put( o );
temp.put( name );
bindings.put( c, temp );
}
} else {
bindings.put( c, name );
}
}
public IBinding getBinding(IASTName name, boolean forceResolve) throws DOMException {
char [] c = name.toCharArray();
if( bindings == null )
return null;
Object obj = bindings.get( c );
if( obj != null ){
if( obj instanceof ObjectSet ) {
if( forceResolve )
return CPPSemantics.resolveAmbiguities( name, ((ObjectSet) obj).keyArray() );
IBinding [] bs = null;
Object [] os = ((ObjectSet) obj).keyArray();
for( int i = 0; i < os.length; i++ ){
if( os[i] instanceof IASTName ){
IASTName n = (IASTName) os[i];
if( n instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
n = ns[ ns.length - 1 ];
}
bs = (IBinding[]) ArrayUtil.append( IBinding.class, bs, ((CPPASTName)n).getBinding() );
} else
bs = (IBinding[]) ArrayUtil.append( IBinding.class, bs, os[i] );
}
return CPPSemantics.resolveAmbiguities( name, bs );
} else if( obj instanceof IASTName ){
IBinding binding = null;
if( forceResolve && obj != name )
binding = ((IASTName)obj).resolveBinding();
else {
IASTName n = (IASTName) obj;
if( n instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
n = ns[ ns.length - 1 ];
}
binding = ((CPPASTName)n).getBinding();
}
if( binding instanceof ICPPCompositeBinding ){
return CPPSemantics.resolveAmbiguities( name, ((ICPPCompositeBinding)binding).getBindings() );
}
return binding;
}
return (IBinding) obj;
}
return null;
}
boolean isfull = false;
public void setFullyCached( boolean full ){
isfull = full;
}
public boolean isFullyCached(){
return isfull;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String)
*/
public IBinding[] find(String name) throws DOMException {
char [] n = name.toCharArray();
if( isFullyCached() ){
if( bindings != null ) {
Object o = bindings.get( n );
if( o instanceof IBinding[] )
return (IBinding[]) ArrayUtil.trim( IBinding.class, (Object[]) o );
return new IBinding[] { (IBinding) o };
}
} else {
LookupData data = new LookupData( n );
try {
data.foundItems = CPPSemantics.lookupInScope( data, this, null, null );
} catch ( DOMException e ) {
}
if( data.foundItems != null ){
IASTName [] ns = (IASTName[]) data.foundItems;
ObjectSet set = new ObjectSet( ns.length );
for( int i = 0; i < ns.length && ns[i] != null; i++ ){
set.put( ns[i].resolveBinding() );
}
return (IBinding[]) ArrayUtil.trim( IBinding.class, set.keyArray(), true );
}
}
return new IBinding[0];
}
}

View file

@ -41,7 +41,6 @@ import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTReturnStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStandardFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
@ -199,7 +198,8 @@ public class CPPSemantics {
} else if( p1 instanceof ICPPASTQualifiedName && p2 instanceof ICPPASTNamedTypeSpecifier ){
IASTNode p3 = p2.getParent();
return p3 instanceof IASTTypeId && p3.getParent() instanceof ICPPASTNewExpression;
}
} else if( p1 instanceof IASTFunctionCallExpression || p2 instanceof IASTFunctionCallExpression )
return true;
return false;
}
public boolean qualified(){
@ -437,7 +437,7 @@ public class CPPSemantics {
IBinding [] ctors = cls.getConstructors();
if( ctors.length > 0 && !(ctors[0] instanceof IProblemBinding) ){
//then use the class scope to resolve which one.
binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding( data.astName );
binding = ((ICPPClassScope)cls.getCompositeScope()).getBinding( data.astName, true );
}
} catch ( DOMException e ) {
binding = e.getProblem();
@ -451,23 +451,7 @@ public class CPPSemantics {
if( binding != null && !( binding instanceof IProblemBinding ) ){
if( data.forDefinition() ){
addDefinition( binding, data.astName );
} else if( data.forUsingDeclaration() ){
IASTNode node = CPPVisitor.getContainingBlockItem( data.astName );
ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope( node );
try {
if( binding instanceof ICPPCompositeBinding ){
IBinding [] bs = ((ICPPCompositeBinding)binding).getBindings();
for( int i = 0; i < bs.length; i++ ) {
scope.addBinding( bs[i] );
}
} else {
scope.addBinding( binding );
}
} catch ( DOMException e ) {
}
}
}
}
if( binding == null )
binding = new ProblemBinding(IProblemBinding.SEMANTIC_NAME_NOT_FOUND, data.name );
@ -651,16 +635,29 @@ public class CPPSemantics {
ArrayWrapper directives = null;
if( !data.usingDirectivesOnly ){
IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName );
if( binding == null ||
(scope instanceof ICPPNamespaceScope && !((ICPPNamespaceScope) scope).isFullyResolved( data.astName ) ) ||
!( CPPSemantics.declaredBefore( binding, data.astName ) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) )
{
directives = new ArrayWrapper();
mergeResults( data, lookupInScope( data, scope, blockItem, directives ), true );
if( scope.isFullyCached() && !data.prefixLookup ){
IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName, true );
if( binding != null &&
( CPPSemantics.declaredBefore( binding, data.astName ) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) )
{
mergeResults( data, binding, true );
}
} else {
mergeResults( data, binding, true );
mergeResults( data, lookupInScope( data, scope, blockItem, null ), true );
}
if( !data.hasResults() && scope instanceof ICPPNamespaceScope ){
directives = new ArrayWrapper();
directives.array = ((ICPPNamespaceScope) scope).getUsingDirectives();
if( directives.array != null ){
for( int i = 0; i < directives.array.length; i++ ){
if( !CPPSemantics.declaredBefore( directives.array[i], blockItem ) ){
directives.array[i] = null;
directives.array = ArrayUtil.trim( IASTNode.class, directives.array );
}
}
}
}
}
@ -943,26 +940,29 @@ public class CPPSemantics {
item = nodes[idx];
}
}
if( !checkWholeClassScope && blockItem != null && ((ASTNode)item).getOffset() > ((ASTNode) blockItem).getOffset() )
break;
if( item != blockItem || data.includeBlockItem( item ) ){
if( !data.ignoreUsingDirectives &&
( item instanceof ICPPASTUsingDirective ||
(item instanceof ICPPASTNamespaceDefinition &&
((ICPPASTNamespaceDefinition)item).getName().toCharArray().length == 0) ) )
if( item instanceof ICPPASTUsingDirective ||
(item instanceof ICPPASTNamespaceDefinition &&
((ICPPASTNamespaceDefinition)item).getName().toCharArray().length == 0) )
{
if( scope instanceof ICPPNamespaceScope )
((ICPPNamespaceScope)scope).addUsingDirective( item );
} else {
possible = collectResult( data, scope, item, (item == parent) );
if( possible != null &&
(checkWholeClassScope || declaredBefore( possible, data.astName )) &&
(item != blockItem || data.includeBlockItem( item )) )
{
if( usingDirectives != null )
usingDirectives.array = ArrayUtil.append( usingDirectives.array, item );
} else {
possible = collectResult( data, scope, item, (item == parent) );
if( possible != null && (checkWholeClassScope || declaredBefore( possible, data.astName )) ){
found = (IASTName[]) ArrayUtil.append( IASTName.class, found, possible );
if( data.considerConstructors ||
!( possible.getParent() instanceof IASTDeclarator &&
CPPVisitor.isConstructor( scope, (IASTDeclarator) possible.getParent() ) ) )
{
found = (IASTName[]) ArrayUtil.append( IASTName.class, found, possible );
}
}
}
if( item == blockItem && !checkWholeClassScope )
break;
if( idx > -1 && ++idx < nodes.length ){
item = nodes[idx];
} else {
@ -1001,6 +1001,8 @@ public class CPPSemantics {
}
}
}
scope.setFullyCached( true );
return found;
}
@ -1022,12 +1024,32 @@ public class CPPSemantics {
}
data.visited.put( temp );
ArrayWrapper usings = new ArrayWrapper();
IASTName[] found = lookupInScope( data, temp, null, usings );
mergeResults( data, found, false );
boolean found = false;
if( temp.isFullyCached() && !data.prefixLookup ){
IBinding binding = temp.getBinding( data.astName, true );
if( binding != null &&
( CPPSemantics.declaredBefore( binding, data.astName ) ||
(scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) )
{
mergeResults( data, binding, true );
found = true;
}
} else {
IASTName [] f = lookupInScope( data, temp, null, null );
if( f != null ) {
mergeResults( data, f, true );
found = true;
}
}
if( !found && temp instanceof ICPPNamespaceScope ){
usings.array = ((ICPPNamespaceScope) temp).getUsingDirectives();
}
//only consider the transitive using directives if we are an unqualified
//lookup, or we didn't find the name in decl
if( usings.array != null && usings.array.length > 0 && (!data.qualified() || found == null ) ){
if( usings.array != null && usings.array.length > 0 && (!data.qualified() || !found ) ){
transitives = ArrayUtil.addAll( Object.class, transitives, usings.array );
}
}
@ -1035,7 +1057,7 @@ public class CPPSemantics {
return transitives;
}
static private IASTName collectResult( CPPSemantics.LookupData data, ICPPScope scope, IASTNode node, boolean checkAux ){
static private IASTName collectResult( CPPSemantics.LookupData data, ICPPScope scope, IASTNode node, boolean checkAux ) throws DOMException{
IASTDeclaration declaration = null;
if( node instanceof IASTDeclaration )
declaration = (IASTDeclaration) node;
@ -1049,6 +1071,7 @@ public class CPPSemantics {
while( dtor.getNestedDeclarator() != null )
dtor = dtor.getNestedDeclarator();
IASTName declName = dtor.getName();
scope.addName( declName );
if( nameMatches( data, declName.toCharArray() ) ) {
return declName;
}
@ -1058,50 +1081,51 @@ public class CPPSemantics {
if( declaration instanceof IASTSimpleDeclaration ){
IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration;
if( !data.typesOnly || simpleDeclaration.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ) {
IASTDeclarator [] declarators = simpleDeclaration.getDeclarators();
for( int i = 0; i < declarators.length; i++ ){
IASTDeclarator declarator = declarators[i];
while( declarator.getNestedDeclarator() != null )
declarator = declarator.getNestedDeclarator();
if( data.considerConstructors || !CPPVisitor.isConstructor( scope, declarator ) ){
IASTName declaratorName = declarator.getName();
if( nameMatches( data, declaratorName.toCharArray() ) ) {
return declaratorName;
}
IASTDeclarator [] declarators = simpleDeclaration.getDeclarators();
for( int i = 0; i < declarators.length; i++ ){
IASTDeclarator declarator = declarators[i];
while( declarator.getNestedDeclarator() != null )
declarator = declarator.getNestedDeclarator();
IASTName declaratorName = declarator.getName();
scope.addName( declaratorName );
if( !data.typesOnly || simpleDeclaration.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ) {
if( nameMatches( data, declaratorName.toCharArray() ) ) {
return declaratorName;
}
}
}
//decl spec
IASTDeclSpecifier declSpec = simpleDeclaration.getDeclSpecifier();
if( declSpec instanceof IASTElaboratedTypeSpecifier ){
if( declarators.length == 0 && declSpec instanceof IASTElaboratedTypeSpecifier ){
IASTName elabName = ((IASTElaboratedTypeSpecifier)declSpec).getName();
scope.addName( elabName );
if( nameMatches( data, elabName.toCharArray() ) ) {
return elabName;
}
} else if( declSpec instanceof ICPPASTCompositeTypeSpecifier ){
IASTName compName = ((IASTCompositeTypeSpecifier)declSpec).getName();
scope.addName( compName );
if( nameMatches( data, compName.toCharArray() ) ) {
return compName;
}
} else if( declSpec instanceof IASTEnumerationSpecifier ){
IASTEnumerationSpecifier enumeration = (IASTEnumerationSpecifier) declSpec;
IASTName eName = enumeration.getName();
scope.addName( eName );
if( nameMatches( data, eName.toCharArray() ) ) {
return eName;
}
if( !data.typesOnly ) {
//check enumerators too
IASTEnumerator [] list = enumeration.getEnumerators();
for( int i = 0; i < list.length; i++ ) {
IASTEnumerator enumerator = list[i];
if( enumerator == null ) break;
eName = enumerator.getName();
if( nameMatches( data, eName.toCharArray() ) ) {
return eName;
}
}
//check enumerators too
IASTEnumerator [] list = enumeration.getEnumerators();
for( int i = 0; i < list.length; i++ ) {
IASTEnumerator enumerator = list[i];
if( enumerator == null ) break;
eName = enumerator.getName();
scope.addName( eName );
if( !data.typesOnly && nameMatches( data, eName.toCharArray() ) ) {
return eName;
}
}
}
} else if( declaration instanceof ICPPASTUsingDeclaration ){
@ -1111,21 +1135,21 @@ public class CPPSemantics {
IASTName [] ns = ((ICPPASTQualifiedName)name).getNames();
name = ns[ ns.length - 1 ];
}
scope.addName( name );
if( nameMatches( data, name.toCharArray() ) ) {
return name;
}
} else if( declaration instanceof ICPPASTNamespaceDefinition ){
IASTName namespaceName = ((ICPPASTNamespaceDefinition) declaration).getName();
scope.addName( namespaceName );
if( nameMatches( data, namespaceName.toCharArray() ) )
return namespaceName;
} else if( declaration instanceof ICPPASTNamespaceAlias ){
IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
scope.addName( alias );
if( nameMatches( data, alias.toCharArray() ) )
return alias;
}
if( data.typesOnly )
return null;
} else
if( declaration instanceof IASTFunctionDefinition ){
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
@ -1133,27 +1157,10 @@ public class CPPSemantics {
//check the function itself
IASTName declName = declarator.getName();
if( data.considerConstructors || !CPPVisitor.isConstructor( scope, declarator ) ){
if( nameMatches( data, declName.toCharArray() ) ) {
return declName;
}
}
if( checkAux ) {
//check the parameters
if ( declarator instanceof IASTStandardFunctionDeclarator ) {
IASTParameterDeclaration [] parameters = ((IASTStandardFunctionDeclarator)declarator).getParameters();
for( int i = 0; i < parameters.length; i++ ){
IASTParameterDeclaration parameterDeclaration = parameters[i];
if( parameterDeclaration == null ) break;
IASTDeclarator dtor = parameterDeclaration.getDeclarator();
while( dtor.getNestedDeclarator() != null )
dtor = dtor.getNestedDeclarator();
declName = dtor.getName();
if( nameMatches( data, declName.toCharArray() ) ) {
return declName;
}
}
}
scope.addName( declName );
if( !data.typesOnly && nameMatches( data, declName.toCharArray() ) ) {
return declName;
}
}
@ -1176,12 +1183,15 @@ public class CPPSemantics {
}
}
static protected IBinding resolveAmbiguities( IASTName name, IBinding[] bindings ){
bindings = (IBinding[]) ArrayUtil.trim( IBinding.class, bindings );
static protected IBinding resolveAmbiguities( IASTName name, Object[] bindings ){
bindings = ArrayUtil.trim( Object.class, bindings );
if( bindings == null || bindings.length == 0 )
return null;
else if( bindings.length == 1 )
return bindings[ 0 ];
else if( bindings.length == 1 ){
if( bindings[0] instanceof IASTName )
return ((IASTName) bindings[ 0 ]).resolveBinding();
return (IBinding) bindings[0];
}
LookupData data = createLookupData( name, false );
data.foundItems = bindings;
@ -1206,7 +1216,7 @@ public class CPPSemantics {
nd = (ASTNode) cpp.getDefinition();
else
return true;
} else if( obj instanceof IASTName ) {
} else if( obj instanceof ASTNode ){
nd = (ASTNode) obj;
}
if( nd != null ){
@ -1222,10 +1232,13 @@ public class CPPSemantics {
} else {
pointOfDecl = nd.getOffset() + nd.getLength();
}
} else if( prop == ICPPASTNamespaceAlias.ALIAS_NAME ){
nd = (ASTNode) nd.getParent();
pointOfDecl = nd.getOffset() + nd.getLength();
} else
pointOfDecl = nd.getOffset();
return ( pointOfDecl <= ((ASTNode)node).getOffset() );
return ( pointOfDecl < ((ASTNode)node).getOffset() );
}
return false;
@ -1243,24 +1256,23 @@ public class CPPSemantics {
Object [] items = (Object[]) data.foundItems;
for( int i = 0; i < items.length && items[i] != null; i++ ){
Object o = items[i];
boolean declaredBefore = declaredBefore( o, name );
if( !data.checkWholeClassScope() && !declaredBefore )
continue;
if( o instanceof IASTName ){
temp = ((IASTName) o).resolveBinding();
if( temp == null )
continue;
IScope scope = temp.getScope();
if( scope instanceof CPPNamespaceScope ){
((CPPNamespaceScope)scope).setFullyResolved( (IASTName) o );
}
} else if( o instanceof IBinding ){
temp = (IBinding) o;
if( !( temp instanceof ICPPMember ) && !declaredBefore( temp, name ) )
continue;
} else
continue;
if( !( temp instanceof ICPPMember ) && !declaredBefore )
continue;
if( temp instanceof ICPPCompositeBinding ){
IBinding [] bindings = ((ICPPCompositeBinding) temp).getBindings();
//data.foundItems = ArrayUtil.addAll( Object.class, data.foundItems, bindings );
mergeResults( data, bindings, false );
items = (Object[]) data.foundItems;
continue;
@ -1301,15 +1313,6 @@ public class CPPSemantics {
if( type != null ) {
if( data.typesOnly || (obj == null && fns == null) )
return type;
// IScope typeScope = type.getScope();
// if( obj != null && obj.getScope() != typeScope ){
// return new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
// } else if( fns != null ){
// for( int i = 0; i < fns.length && fns[i] != null; i++ ){
// if( ((IBinding)fns[i]).getScope() != typeScope )
// return new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
// }
// }
}
if( fns != null){
if( obj != null )
@ -1455,7 +1458,6 @@ public class CPPSemantics {
IType source = null; //parameter we are called with
IType target = null; //function's parameter
// ITypeInfo voidInfo = null; //used to compare f() and f(void)
int comparison;
Cost cost = null; //the cost of converting source to target

View file

@ -153,9 +153,9 @@ public class CPPVisitor implements ICPPASTVisitor {
{
binding = CPPSemantics.resolveBinding( name );
if( binding instanceof IProblemBinding && parent instanceof ICPPASTQualifiedName ){
if( ((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND ){
//if( ((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_NAME_NOT_FOUND ){
parent = parent.getParent();
}
//}
} else {
return binding;
}
@ -190,10 +190,10 @@ public class CPPVisitor implements ICPPASTVisitor {
IASTName name = gotoStatement.getName();
IBinding binding;
try {
binding = functionScope.getBinding( name );
binding = functionScope.getBinding( name, false );
if( binding == null ){
binding = new CPPLabel( gotoStatement.getName() );
functionScope.addBinding( binding );
binding = new CPPLabel( name );
functionScope.addName( name );
}
} catch ( DOMException e ) {
binding = e.getProblem();
@ -207,12 +207,12 @@ public class CPPVisitor implements ICPPASTVisitor {
IASTName name = labelStatement.getName();
IBinding binding;
try {
binding = functionScope.getBinding( name );
binding = functionScope.getBinding( name, false );
if( binding == null ){
binding = new CPPLabel( labelStatement.getName() );
functionScope.addBinding( binding );
binding = new CPPLabel( name );
functionScope.addName( name );
} else {
((CPPLabel)binding).setLabelStatement( labelStatement.getName() );
((CPPLabel)binding).setLabelStatement( name );
}
} catch ( DOMException e ) {
binding = e.getProblem();
@ -225,10 +225,10 @@ public class CPPVisitor implements ICPPASTVisitor {
ICPPScope scope = (ICPPScope) getContainingScope( enumerator );
IBinding enumtor;
try {
enumtor = scope.getBinding( enumerator.getName() );
enumtor = scope.getBinding( enumerator.getName(), false );
if( enumtor == null ){
enumtor = new CPPEnumerator( enumerator.getName() );
scope.addBinding( enumtor );
scope.addName( enumerator.getName() );
}
} catch ( DOMException e ) {
enumtor = e.getProblem();
@ -242,10 +242,10 @@ public class CPPVisitor implements ICPPASTVisitor {
ICPPScope scope = (ICPPScope) getContainingScope( specifier );
IBinding enumeration;
try {
enumeration = scope.getBinding( specifier.getName() );
enumeration = scope.getBinding( specifier.getName(), false );
if( enumeration == null ){
enumeration = new CPPEnumeration( specifier.getName() );
scope.addBinding( enumeration );
scope.addName( specifier.getName() );
}
} catch ( DOMException e ) {
enumeration = e.getProblem();
@ -307,11 +307,12 @@ public class CPPVisitor implements ICPPASTVisitor {
}
}
try {
binding = scope.getBinding( elabType.getName() );
binding = scope.getBinding( elabType.getName(), false );
if( binding == null ){
if( elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum )
if( elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum ){
binding = new CPPClassType( elabType.getName() );
scope.addBinding( binding );
scope.addName( elabType.getName() );
}
} else if( binding instanceof ICPPClassType ){
((CPPClassType)binding).addDeclaration( elabType );
}
@ -330,10 +331,10 @@ public class CPPVisitor implements ICPPASTVisitor {
ICPPScope scope = (ICPPScope) getContainingScope( name );
IBinding binding;
try {
binding = scope.getBinding( compType.getName() );
binding = scope.getBinding( compType.getName(), false );
if( binding == null || !(binding instanceof ICPPClassType) ){
binding = new CPPClassType( compType.getName() );
scope.addBinding( binding );
scope.addName( compType.getName() );
} else {
((CPPClassType)binding).addDefinition( compType );
}
@ -349,10 +350,10 @@ public class CPPVisitor implements ICPPASTVisitor {
ICPPScope scope = (ICPPScope) getContainingScope( namespaceDef );
IBinding binding;
try {
binding = scope.getBinding( namespaceDef.getName() );
binding = scope.getBinding( namespaceDef.getName(), false );
if( binding == null ){
binding = new CPPNamespace( namespaceDef.getName() );
scope.addBinding( binding );
scope.addName( namespaceDef.getName() );
}
} catch ( DOMException e ) {
binding = e.getProblem();
@ -370,13 +371,19 @@ public class CPPVisitor implements ICPPASTVisitor {
}
private static IBinding createBinding( IASTDeclarator declarator ){
IASTNode parent = declarator.getParent();
if( parent instanceof IASTTypeId )
return CPPSemantics.resolveBinding( declarator.getName() );
while( declarator.getNestedDeclarator() != null )
declarator = declarator.getNestedDeclarator();
IASTName name = declarator.getName();
if( name instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)name).getNames();
name = ns[ ns.length - 1 ];
}
while( parent instanceof IASTDeclarator ){
parent = parent.getParent();
}
@ -402,7 +409,7 @@ public class CPPVisitor implements ICPPASTVisitor {
IBinding binding;
try {
binding = ( scope != null ) ? scope.getBinding( declarator.getName() ) : null;
binding = ( scope != null ) ? scope.getBinding( declarator.getName(), false ) : null;
} catch ( DOMException e ) {
binding = null;
}
@ -470,7 +477,7 @@ public class CPPVisitor implements ICPPASTVisitor {
if( scope != null && binding != null ){
try {
scope.addBinding( binding );
scope.addName( name );
} catch ( DOMException e1 ) {
}
}
@ -591,6 +598,10 @@ public class CPPVisitor implements ICPPASTVisitor {
return ((ICPPClassType)binding).getCompositeScope();
} else if( binding instanceof ICPPNamespace ){
return ((ICPPNamespace)binding).getNamespaceScope();
} else if( binding instanceof IProblemBinding ){
if( binding instanceof ICPPScope )
return (IScope) binding;
return new CPPScope.CPPScopeProblem( -1, names[i-1].toCharArray() );
}
}
else if( ((ICPPASTQualifiedName)parent).isFullyQualified() )