diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index fc3bd206ceb..d6bc508e143 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -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 ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index b52d193a63e..589e9ad8fc7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -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; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 529fc2a1e60..3cee71a9fce 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -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 ) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index 06351fa6c56..632baa05c91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -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; }