mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-30 21:55:31 +02:00
fix bug 86470 - various issues with using declarations
This commit is contained in:
parent
b9dc18ad86
commit
23013c436d
4 changed files with 253 additions and 33 deletions
|
@ -55,6 +55,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPointerToMember;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTWhileStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPCompositeBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
|
@ -2399,5 +2400,133 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
assertSame( decls[2], col.getName(3) );
|
||||
assertSame( decls[3], col.getName(5) );
|
||||
}
|
||||
|
||||
public void testBug86470_1() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("namespace A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( char ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( int ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("using A::f; \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.getVisitor().visitTranslationUnit(col);
|
||||
|
||||
IBinding b = col.getName(7).resolveBinding();
|
||||
IASTName [] decls = tu.getDeclarations( b );
|
||||
assertEquals( decls.length, 2 );
|
||||
assertSame( decls[0], col.getName(1) );
|
||||
assertSame( decls[1], col.getName(3) );
|
||||
}
|
||||
|
||||
public void testBug86470_2() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("namespace A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( int ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( double ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("namespace B { \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( int ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( double ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( char ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("void g() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" using A::f; \n"); //$NON-NLS-1$
|
||||
buffer.append(" using B::f; \n"); //$NON-NLS-1$
|
||||
buffer.append(" f( 'c' ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.getVisitor().visitTranslationUnit(col);
|
||||
|
||||
IFunction f_decl = (IFunction) col.getName(10).resolveBinding();
|
||||
IFunction f_ref = (IFunction) col.getName(19).resolveBinding();
|
||||
|
||||
assertSame( f_decl, f_ref );
|
||||
}
|
||||
|
||||
public void testBug86470_3() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("namespace A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" struct g {}; \n"); //$NON-NLS-1$
|
||||
buffer.append(" void g ( char ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("void f() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" using A::g; \n"); //$NON-NLS-1$
|
||||
buffer.append(" g('a'); \n"); //$NON-NLS-1$
|
||||
buffer.append(" struct g gg; \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.getVisitor().visitTranslationUnit(col);
|
||||
|
||||
IBinding ref1 = col.getName(8).resolveBinding();
|
||||
IBinding ref2 = col.getName(9).resolveBinding();
|
||||
|
||||
ICPPClassType g_struct = (ICPPClassType) col.getName(1).resolveBinding();
|
||||
IFunction g_func = (IFunction) col.getName(2).resolveBinding();
|
||||
|
||||
assertSame( g_struct, ref2 );
|
||||
assertSame( g_func, ref1 );
|
||||
|
||||
ICPPCompositeBinding comp = (ICPPCompositeBinding) col.getName(7).resolveBinding();
|
||||
IASTName [] decls = tu.getDeclarations(comp);
|
||||
assertEquals( decls.length, 2 );
|
||||
assertSame( decls[0], col.getName(1) );
|
||||
assertSame( decls[1], col.getName(2) );
|
||||
}
|
||||
|
||||
public void testBug86470_4() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("namespace A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" int x; \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("namespace B { \n"); //$NON-NLS-1$
|
||||
buffer.append(" struct x {}; \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("void f() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" using A::x; \n"); //$NON-NLS-1$
|
||||
buffer.append(" using B::x; \n"); //$NON-NLS-1$
|
||||
buffer.append(" x = 1; \n"); //$NON-NLS-1$
|
||||
buffer.append(" struct x xx; \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.getVisitor().visitTranslationUnit(col);
|
||||
|
||||
IBinding ref1 = col.getName(11).resolveBinding();
|
||||
IBinding ref2 = col.getName(12).resolveBinding();
|
||||
|
||||
ICPPClassType x_struct = (ICPPClassType) col.getName(3).resolveBinding();
|
||||
IVariable x_var = (IVariable) col.getName(1).resolveBinding();
|
||||
|
||||
assertSame( x_struct, ref2 );
|
||||
assertSame( x_var, ref1 );
|
||||
}
|
||||
|
||||
public void testBug86470_5() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("namespace A { \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( int ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( double ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
buffer.append("void g() { \n"); //$NON-NLS-1$
|
||||
buffer.append(" void f( char ); \n"); //$NON-NLS-1$
|
||||
buffer.append(" using A::f; \n"); //$NON-NLS-1$
|
||||
buffer.append(" f( 3.5 ); \n"); //$NON-NLS-1$
|
||||
buffer.append("} \n"); //$NON-NLS-1$
|
||||
|
||||
IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.getVisitor().visitTranslationUnit(col);
|
||||
|
||||
IFunction f = (IFunction) col.getName(3).resolveBinding();
|
||||
|
||||
assertInstances( col, f, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -160,4 +160,11 @@ public class ArrayUtil {
|
|||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public static boolean contains( Object [] array, Object obj ){
|
||||
if( array == null ) return false;
|
||||
for( int i = 0; i < array.length; i++ )
|
||||
if( array[i] == obj ) return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,9 +161,17 @@ public class CPPSemantics {
|
|||
public boolean forUsingDeclaration(){
|
||||
if( astName == null ) return false;
|
||||
IASTNode p1 = astName.getParent();
|
||||
IASTNode p2 = p1.getParent();
|
||||
return ( ( p1 instanceof ICPPASTUsingDeclaration ) ||
|
||||
( p1 instanceof ICPPASTQualifiedName && p2 instanceof ICPPASTUsingDeclaration ) );
|
||||
if( p1 instanceof ICPPASTUsingDeclaration )
|
||||
return true;
|
||||
|
||||
if( p1 instanceof ICPPASTQualifiedName ){
|
||||
IASTNode p2 = p1.getParent();
|
||||
if( p2 instanceof ICPPASTUsingDeclaration ){
|
||||
IASTName [] ns = ((ICPPASTQualifiedName) p1 ).getNames();
|
||||
return (ns[ ns.length - 1 ] == astName);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public boolean forDefinition(){
|
||||
if( astName == null ) return false;
|
||||
|
@ -445,7 +453,7 @@ public class CPPSemantics {
|
|||
if( binding instanceof ICPPCompositeBinding ){
|
||||
IBinding [] bs = ((ICPPCompositeBinding)binding).getBindings();
|
||||
for( int i = 0; i < bs.length; i++ ) {
|
||||
scope.addBinding( binding );
|
||||
scope.addBinding( bs[i] );
|
||||
}
|
||||
} else {
|
||||
scope.addBinding( binding );
|
||||
|
@ -1200,6 +1208,7 @@ public class CPPSemantics {
|
|||
IBinding [] bindings = ((ICPPCompositeBinding) temp).getBindings();
|
||||
//data.foundItems = ArrayUtil.addAll( Object.class, data.foundItems, bindings );
|
||||
mergeResults( data, bindings, false );
|
||||
items = (Object[]) data.foundItems;
|
||||
continue;
|
||||
} else if( temp instanceof IType ){
|
||||
if( type == null ){
|
||||
|
@ -1217,19 +1226,36 @@ public class CPPSemantics {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( data.forUsingDeclaration() ){
|
||||
IBinding [] bindings = null;
|
||||
if( obj != null ){
|
||||
if( fns != null ) return new ProblemBinding( IProblemBinding.SEMANTIC_AMBIGUOUS_LOOKUP, data.name );
|
||||
if( type == null ) return obj;
|
||||
bindings = (IBinding[]) ArrayUtil.append( IBinding.class, bindings, obj );
|
||||
bindings = (IBinding[]) ArrayUtil.append( IBinding.class, bindings, type );
|
||||
} else {
|
||||
if( fns == null ) return type;
|
||||
bindings = (IBinding[]) ArrayUtil.addAll( IBinding.class, bindings, fns );
|
||||
bindings = (IBinding[]) ArrayUtil.append( IBinding.class, bindings, type );
|
||||
}
|
||||
bindings = (IBinding[]) ArrayUtil.trim( IBinding.class, bindings );
|
||||
if( bindings.length == 1 ) return bindings[0];
|
||||
ICPPCompositeBinding composite = new CPPCompositeBinding( bindings );
|
||||
return composite;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
// 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 )
|
||||
|
|
|
@ -121,6 +121,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPCompositeBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
|
@ -783,6 +784,7 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
private static final int KIND_OBJ_FN = 2;
|
||||
private static final int KIND_TYPE = 3;
|
||||
private static final int KIND_NAMESPACE = 4;
|
||||
private static final int KIND_COMPOSITE = 5;
|
||||
|
||||
|
||||
public CollectDeclarationsAction( IBinding binding ){
|
||||
|
@ -800,7 +802,10 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
}
|
||||
else if( binding instanceof ICPPNamespace) {
|
||||
kind = KIND_NAMESPACE;
|
||||
} else
|
||||
}
|
||||
else if( binding instanceof ICPPCompositeBinding )
|
||||
kind = KIND_COMPOSITE;
|
||||
else
|
||||
kind = KIND_OBJ_FN;
|
||||
}
|
||||
|
||||
|
@ -817,6 +822,7 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
break;
|
||||
return PROCESS_CONTINUE;
|
||||
case KIND_TYPE:
|
||||
case KIND_COMPOSITE:
|
||||
if( prop == IASTCompositeTypeSpecifier.TYPE_NAME ||
|
||||
prop == IASTEnumerationSpecifier.ENUMERATION_NAME )
|
||||
{
|
||||
|
@ -837,8 +843,8 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
return PROCESS_CONTINUE;
|
||||
if( kind == KIND_TYPE )
|
||||
return PROCESS_CONTINUE;
|
||||
case KIND_OBJ_FN:
|
||||
if( prop == IASTDeclarator.DECLARATOR_NAME ||
|
||||
prop == IASTEnumerationSpecifier.IASTEnumerator.ENUMERATOR_NAME )
|
||||
|
@ -855,14 +861,28 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
if( binding != null && name.resolveBinding() == binding )
|
||||
if( binding != null )
|
||||
{
|
||||
if( decls.length == idx ){
|
||||
IASTName [] temp = new IASTName[ decls.length * 2 ];
|
||||
System.arraycopy( decls, 0, temp, 0, decls.length );
|
||||
decls = temp;
|
||||
}
|
||||
decls[idx++] = name;
|
||||
IBinding candidate = name.resolveBinding();
|
||||
|
||||
boolean found = false;
|
||||
if( binding instanceof ICPPCompositeBinding ){
|
||||
try {
|
||||
found = ArrayUtil.contains( ((ICPPCompositeBinding)binding).getBindings(), candidate );
|
||||
} catch ( DOMException e ) {
|
||||
}
|
||||
} else {
|
||||
found = ( binding == candidate );
|
||||
}
|
||||
|
||||
if( found ){
|
||||
if( decls.length == idx ){
|
||||
IASTName [] temp = new IASTName[ decls.length * 2 ];
|
||||
System.arraycopy( decls, 0, temp, 0, decls.length );
|
||||
decls = temp;
|
||||
}
|
||||
decls[idx++] = name;
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
@ -887,6 +907,7 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
private static final int KIND_OBJ_FN = 2;
|
||||
private static final int KIND_TYPE = 3;
|
||||
private static final int KIND_NAMESPACE = 4;
|
||||
private static final int KIND_COMPOSITE = 5;
|
||||
|
||||
|
||||
public CollectReferencesAction( IBinding binding ){
|
||||
|
@ -904,7 +925,9 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
}
|
||||
else if( binding instanceof ICPPNamespace) {
|
||||
kind = KIND_NAMESPACE;
|
||||
} else
|
||||
} else if( binding instanceof ICPPCompositeBinding )
|
||||
kind = KIND_COMPOSITE;
|
||||
else
|
||||
kind = KIND_OBJ_FN;
|
||||
}
|
||||
|
||||
|
@ -924,6 +947,7 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
break;
|
||||
return PROCESS_CONTINUE;
|
||||
case KIND_TYPE:
|
||||
case KIND_COMPOSITE:
|
||||
if( prop == IASTNamedTypeSpecifier.NAME ||
|
||||
prop == ICPPASTPointerToMember.NAME ||
|
||||
prop == ICPPASTTypenameExpression.TYPENAME ||
|
||||
|
@ -942,7 +966,8 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
break;
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
if( kind == KIND_TYPE )
|
||||
return PROCESS_CONTINUE;
|
||||
case KIND_OBJ_FN:
|
||||
if( prop == IASTIdExpression.ID_NAME ||
|
||||
prop == IASTFieldReference.FIELD_NAME ||
|
||||
|
@ -966,13 +991,46 @@ public class CPPVisitor implements ICPPASTVisitor {
|
|||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
||||
if( binding != null && name.resolveBinding() == binding ){
|
||||
if( refs.length == idx ){
|
||||
IASTName [] temp = new IASTName[ refs.length * 2 ];
|
||||
System.arraycopy( refs, 0, temp, 0, refs.length );
|
||||
refs = temp;
|
||||
}
|
||||
refs[idx++] = name;
|
||||
if( binding != null ){
|
||||
IBinding potential = name.resolveBinding();
|
||||
IBinding [] bs = null;
|
||||
IBinding candidate = null;
|
||||
int n = -1;
|
||||
if( potential instanceof ICPPCompositeBinding ){
|
||||
try {
|
||||
bs = ((ICPPCompositeBinding)potential).getBindings();
|
||||
} catch ( DOMException e ) {
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
candidate = bs[ ++n ];
|
||||
} else {
|
||||
candidate = potential;
|
||||
}
|
||||
|
||||
while( candidate != null ) {
|
||||
boolean found = false;
|
||||
if( binding instanceof ICPPCompositeBinding ){
|
||||
try {
|
||||
found = ArrayUtil.contains( ((ICPPCompositeBinding)binding).getBindings(), candidate );
|
||||
} catch ( DOMException e ) {
|
||||
}
|
||||
} else {
|
||||
found = ( binding == candidate );
|
||||
}
|
||||
|
||||
if( found ){
|
||||
if( refs.length == idx ){
|
||||
IASTName [] temp = new IASTName[ refs.length * 2 ];
|
||||
System.arraycopy( refs, 0, temp, 0, refs.length );
|
||||
refs = temp;
|
||||
}
|
||||
refs[idx++] = name;
|
||||
break;
|
||||
}
|
||||
if( n > -1 && ++n < bs.length ){
|
||||
candidate = bs[n];
|
||||
} else break;
|
||||
}
|
||||
}
|
||||
return PROCESS_CONTINUE;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue