1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Correct binding resolution when performed out of order, bug 232300.

This commit is contained in:
Markus Schorn 2008-05-16 17:17:23 +00:00
parent a3566fff4f
commit cec3ad4e98
3 changed files with 140 additions and 54 deletions

View file

@ -4698,4 +4698,27 @@ public class AST2Tests extends AST2BaseTest {
parseAndCheckBindings(code, ParserLanguage.C); parseAndCheckBindings(code, ParserLanguage.C);
parseAndCheckBindings(code, ParserLanguage.CPP); parseAndCheckBindings(code, ParserLanguage.CPP);
} }
// int globalArray[4] = {1,2,3,4};
// void function1(); // decl
//
// void function1() {
// getArray()[0] = 1;
// }
//
// void function2() {
// function1(); // ref
// }
public void testOutOfOrderResolution_Bug232300() throws Exception {
final boolean[] isCpp= {false, true};
String code= getAboveComment();
for (boolean element : isCpp) {
BindingAssertionHelper ba= new BindingAssertionHelper(getAboveComment(), element);
IBinding b1= ba.assertNonProblem("function1(); // decl", 9);
IBinding b2= ba.assertNonProblem("function1() {", 9);
IBinding b3= ba.assertNonProblem("function1(); // ref", 9);
assertSame(b1, b2);
assertSame(b2, b3);
}
}
} }

View file

@ -47,6 +47,7 @@ import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
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.internal.core.dom.parser.IASTInternalScope; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
@ -96,7 +97,8 @@ public class CScope implements ICScope, IASTInternalScope {
private IASTNode physicalNode = null; private IASTNode physicalNode = null;
private boolean isFullyCached = false; private boolean isFullyCached = false;
private CharArrayObjectMap [] bindings = { CharArrayObjectMap.EMPTY_MAP, CharArrayObjectMap.EMPTY_MAP }; private CharArrayObjectMap[] mapsToNameOrBinding = { CharArrayObjectMap.EMPTY_MAP, CharArrayObjectMap.EMPTY_MAP };
private ObjectMap reuseBindings= null;
public CScope( IASTNode physical ){ public CScope( IASTNode physical ){
physicalNode = physical; physicalNode = physical;
@ -148,8 +150,14 @@ public class CScope implements ICScope, IASTInternalScope {
} }
public IBinding getBinding( int namespaceType, char [] name ){ public IBinding getBinding( int namespaceType, char [] name ){
IASTName n = (IASTName) bindings[namespaceType].get( name ); Object o= mapsToNameOrBinding[namespaceType].get(name);
return ( n != null ) ? n.resolveBinding() : null; if (o instanceof IBinding)
return (IBinding) o;
if (o instanceof IASTName)
return ((IASTName) o).resolveBinding();
return null;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -159,8 +167,12 @@ public class CScope implements ICScope, IASTInternalScope {
int type = ( binding instanceof ICompositeType || binding instanceof IEnumeration ) ? int type = ( binding instanceof ICompositeType || binding instanceof IEnumeration ) ?
NAMESPACE_TYPE_TAG : NAMESPACE_TYPE_OTHER; NAMESPACE_TYPE_TAG : NAMESPACE_TYPE_OTHER;
if( bindings[type] != CharArrayObjectMap.EMPTY_MAP ) { final CharArrayObjectMap bindingsMap = mapsToNameOrBinding[type];
bindings[type].remove( binding.getNameCharArray(), 0, binding.getNameCharArray().length); if( bindingsMap != CharArrayObjectMap.EMPTY_MAP ) {
Object o= bindingsMap.remove( binding.getNameCharArray(), 0, binding.getNameCharArray().length);
if (o != null && reuseBindings != null) {
reuseBindings.remove(o);
}
} }
isFullyCached = false; isFullyCached = false;
} }
@ -177,14 +189,35 @@ public class CScope implements ICScope, IASTInternalScope {
*/ */
public void addName( IASTName name ) { public void addName( IASTName name ) {
int type = getNamespaceType( name ); int type = getNamespaceType( name );
if( bindings[type] == CharArrayObjectMap.EMPTY_MAP ) CharArrayObjectMap map = mapsToNameOrBinding[type];
bindings[type] = new CharArrayObjectMap(1); if( map == CharArrayObjectMap.EMPTY_MAP )
map= mapsToNameOrBinding[type] = new CharArrayObjectMap(1);
char [] n = name.toCharArray(); final char [] n = name.toCharArray();
Object current= bindings[type].get( n ); final Object current= map.get( n );
if( !(current instanceof IASTName) || ((CASTName)current).getOffset() > ((CASTName) name).getOffset() ){ if (current instanceof IASTName) {
bindings[type].put( n, name ); final CASTName currentName = (CASTName)current;
if (currentName.getOffset() <= ((CASTName) name).getOffset() ){
return;
}
if (name.getBinding() == null) {
// bug 232300: we need to make sure that the binding is picked up even if the name is removed
// from the cache. Simply assigning it to the name is not enough, because a declaration or
// definition needs to be added to the binding.
IBinding reuseBinding= currentName.getBinding();
if (reuseBinding == null && reuseBindings != null) {
reuseBinding= (IBinding) reuseBindings.get(currentName);
}
if (reuseBinding != null) {
if (reuseBindings == null) {
reuseBindings= new ObjectMap(1);
}
reuseBindings.put(name, reuseBinding);
reuseBindings.remove(currentName);
}
}
} }
map.put(n, name);
} }
private int getNamespaceType( IASTName name ){ private int getNamespaceType( IASTName name ){
@ -213,17 +246,26 @@ public class CScope implements ICScope, IASTInternalScope {
return null; return null;
} }
int type = getNamespaceType( name ); final int type = getNamespaceType( name );
Object o = bindings[type].get( name.toCharArray() ); Object o = mapsToNameOrBinding[type].get( name.toCharArray() );
if( o instanceof IBinding ) if( o instanceof IBinding )
return (IBinding) o; return (IBinding) o;
if (o != null && o != name) { if (o instanceof IASTName) {
IASTName foundName= (IASTName) o; final IASTName n= (IASTName) o;
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) { if (!isTypeDefinition(name) || CVisitor.declaredBefore(n, name)) {
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) { IBinding b= n.getBinding();
return foundName.resolveBinding(); if (b != null)
return b;
if (reuseBindings != null) {
b= (IBinding) reuseBindings.get(n);
if (b != null)
return b;
}
if (resolve && n != name) {
return n.resolveBinding();
} }
} }
} }
@ -274,17 +316,17 @@ public class CScope implements ICScope, IASTInternalScope {
Object[] obj = null; Object[] obj = null;
for (CharArrayObjectMap binding : bindings) { for (CharArrayObjectMap map : mapsToNameOrBinding) {
if (prefixLookup) { if (prefixLookup) {
Object[] keys = binding.keyArray(); Object[] keys = map.keyArray();
for (Object key2 : keys) { for (Object key2 : keys) {
char[] key = (char[]) key2; char[] key = (char[]) key2;
if (CharArrayUtils.equals(key, 0, c.length, c, true)) { if (CharArrayUtils.equals(key, 0, c.length, c, true)) {
obj = ArrayUtil.append(obj, binding.get(key)); obj = ArrayUtil.append(obj, map.get(key));
} }
} }
} else { } else {
obj = ArrayUtil.append(obj, binding.get(c)); obj = ArrayUtil.append(obj, map.get(c));
} }
} }
@ -310,11 +352,24 @@ public class CScope implements ICScope, IASTInternalScope {
IBinding[] result = null; IBinding[] result = null;
for (Object element : obj) { for (Object element : obj) {
if( element instanceof IBinding ) if( element instanceof IBinding ) {
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, element); result = (IBinding[]) ArrayUtil.append(IBinding.class, result, element);
} else if (element instanceof IASTName) {
final IASTName n= (IASTName) element;
IBinding b= n.getBinding();
if (b == null) {
if (reuseBindings != null) {
b= (IBinding) reuseBindings.get(n);
}
if (resolve && b == null && n != name) {
b= n.resolveBinding();
}
}
if (b != null) {
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, b);
}
if( (resolve || ((IASTName)element).getBinding() != null) && ( element != name ) ) }
result = (IBinding[]) ArrayUtil.append(IBinding.class, result, ((IASTName)element).resolveBinding());
} }
return (IBinding[]) ArrayUtil.trim(IBinding.class, result); return (IBinding[]) ArrayUtil.trim(IBinding.class, result);
@ -332,27 +387,6 @@ public class CScope implements ICScope, IASTInternalScope {
return null; return null;
return bindings[0]; return bindings[0];
// IBinding candidate= bindings[0];
// if(candidate instanceof IFunction) {
// IASTNode parent= name.getParent();
// if(parent instanceof IASTFunctionDeclarator) {
// IASTNode parent2= parent.getParent();
// if(parent2 instanceof IASTFunctionDefinition) {
// IASTFunctionDefinition def= (IASTFunctionDefinition) parent2;
// if(def.getDeclSpecifier().getStorageClass()==IASTDeclSpecifier.sc_static) {
// try {
// if(!((IFunction)candidate).isStatic()) {
// return null;
// }
// } catch(DOMException de) {
// CCorePlugin.log(de);
// }
// }
// }
// }
// }
//
// return candidate;
} }
/* (non-Javadoc) /* (non-Javadoc)
@ -380,8 +414,30 @@ public class CScope implements ICScope, IASTInternalScope {
} }
public void flushCache() { public void flushCache() {
bindings[0].clear(); CharArrayObjectMap map= mapsToNameOrBinding[0];
bindings[1].clear(); CharArrayObjectMap builtins= new CharArrayObjectMap(map.size());
for (int i = 0; i < map.size(); i++) {
Object obj= map.getAt(i);
if (obj instanceof IASTName) {
((IASTName) obj).setBinding(null);
} else if (obj instanceof IBinding) {
builtins.put(((IBinding) obj).getNameCharArray(), obj);
}
}
mapsToNameOrBinding[0]= map;
map= mapsToNameOrBinding[1];
builtins= new CharArrayObjectMap(map.size());
for (int i = 0; i < map.size(); i++) {
Object obj= map.getAt(i);
if (obj instanceof IASTName) {
((IASTName) obj).setBinding(null);
} else if (obj instanceof IBinding) {
builtins.put(((IBinding) obj).getNameCharArray(), obj);
}
}
mapsToNameOrBinding[1]= map;
reuseBindings= null;
isFullyCached = false; isFullyCached = false;
} }
@ -391,9 +447,10 @@ public class CScope implements ICScope, IASTInternalScope {
type = NAMESPACE_TYPE_TAG; type = NAMESPACE_TYPE_TAG;
} }
if( bindings[type] == CharArrayObjectMap.EMPTY_MAP ) CharArrayObjectMap map = mapsToNameOrBinding[type];
bindings[type] = new CharArrayObjectMap(2); if( map == CharArrayObjectMap.EMPTY_MAP )
map= mapsToNameOrBinding[type] = new CharArrayObjectMap(2);
bindings[type].put(binding.getNameCharArray(), binding); map.put(binding.getNameCharArray(), binding);
} }
} }

View file

@ -921,7 +921,12 @@ public class CVisitor {
} }
if( parent instanceof IASTParameterDeclaration || parent.getPropertyInParent() == ICASTKnRFunctionDeclarator.FUNCTION_PARAMETER ){ if( parent instanceof IASTParameterDeclaration || parent.getPropertyInParent() == ICASTKnRFunctionDeclarator.FUNCTION_PARAMETER ){
IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) parent.getParent(); IASTDeclarator fdtor = (IASTDeclarator) parent.getParent();
IASTDeclarator nested= fdtor.getNestedDeclarator();
while (nested != null && nested.getPointerOperators().length == 0) {
fdtor= nested;
nested= nested.getNestedDeclarator();
}
IBinding temp = fdtor.getName().resolveBinding(); IBinding temp = fdtor.getName().resolveBinding();
if( temp != null && temp instanceof CFunction ){ if( temp != null && temp instanceof CFunction ){
binding = ((CFunction) temp).resolveParameter( name ); binding = ((CFunction) temp).resolveParameter( name );
@ -939,8 +944,9 @@ public class CVisitor {
if( binding != null && !(binding instanceof IIndexBinding)) { if( binding != null && !(binding instanceof IIndexBinding)) {
if( binding instanceof IFunction ){ if( binding instanceof IFunction ){
IFunction function = (IFunction) binding; IFunction function = (IFunction) binding;
if( function instanceof CFunction ) if( function instanceof CFunction ) {
((CFunction)function).addDeclarator( funcDeclarator ); ((CFunction)function).addDeclarator( funcDeclarator );
}
return function; return function;
} }
binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray() ); binding = new ProblemBinding( name, IProblemBinding.SEMANTIC_INVALID_OVERLOAD, name.toCharArray() );