mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Name resolution for qualified member declarations, bug 222026.
This commit is contained in:
parent
07fd280fc9
commit
4ae9346289
9 changed files with 176 additions and 61 deletions
|
@ -5729,4 +5729,101 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
bh.assertNonProblem("func(qualified)", 4);
|
||||
bh.assertNonProblem("func(unqualified)", 4);
|
||||
}
|
||||
|
||||
|
||||
// class Test {
|
||||
// void Test::member1();
|
||||
// void Test::member2() {};
|
||||
// };
|
||||
// void Test::member1(){
|
||||
// member2();
|
||||
// }
|
||||
public void testQualifiedMemberDeclaration_Bug222026() throws Exception {
|
||||
final String code = getContents(1)[0].toString();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
||||
IBinding b= bh.assertNonProblem("member1", 7);
|
||||
IBinding b2= bh.assertNonProblem("member1(){", 7);
|
||||
assertTrue(b instanceof ICPPMethod);
|
||||
ICPPMethod m1= (ICPPMethod) b;
|
||||
assertEquals("member1", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b= bh.assertNonProblem("member2", 7);
|
||||
b2= bh.assertNonProblem("member2();", 7);
|
||||
assertTrue(b instanceof ICPPMethod);
|
||||
m1= (ICPPMethod) b;
|
||||
assertEquals("member2", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
// different resolution order
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b2= bh.assertNonProblem("member1(){", 7);
|
||||
b= bh.assertNonProblem("member1", 7);
|
||||
assertTrue(b instanceof ICPPMethod);
|
||||
m1= (ICPPMethod) b;
|
||||
assertEquals("member1", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b2= bh.assertNonProblem("member2();", 7);
|
||||
b= bh.assertNonProblem("member2", 7);
|
||||
assertTrue(b instanceof ICPPMethod);
|
||||
m1= (ICPPMethod) b;
|
||||
assertEquals("member2", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
}
|
||||
|
||||
// namespace Test {
|
||||
// void Test::member1();
|
||||
// void Test::member2() {};
|
||||
// }
|
||||
// void Test::member1(){
|
||||
// member2();
|
||||
// }
|
||||
public void testQualifiedMemberDeclarationInNamespace_Bug222026() throws Exception {
|
||||
final String code = getContents(1)[0].toString();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
||||
IBinding b= bh.assertNonProblem("member1", 7);
|
||||
IBinding b2= bh.assertNonProblem("member1(){", 7);
|
||||
assertTrue(b instanceof ICPPFunction);
|
||||
ICPPFunction m1= (ICPPFunction) b;
|
||||
assertEquals("member1", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b= bh.assertNonProblem("member2", 7);
|
||||
b2= bh.assertNonProblem("member2();", 7);
|
||||
assertTrue(b instanceof ICPPFunction);
|
||||
m1= (ICPPFunction) b;
|
||||
assertEquals("member2", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
// different resolution order
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b2= bh.assertNonProblem("member1(){", 7);
|
||||
b= bh.assertNonProblem("member1", 7);
|
||||
assertTrue(b instanceof ICPPFunction);
|
||||
m1= (ICPPFunction) b;
|
||||
assertEquals("member1", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
|
||||
bh= new BindingAssertionHelper(code, true);
|
||||
b2= bh.assertNonProblem("member2();", 7);
|
||||
b= bh.assertNonProblem("member2", 7);
|
||||
assertTrue(b instanceof ICPPFunction);
|
||||
m1= (ICPPFunction) b;
|
||||
assertEquals("member2", m1.getName());
|
||||
assertEquals("Test", m1.getScope().getScopeName().toString());
|
||||
assertSame(b, b2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IScope getParent() {
|
||||
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
|
||||
IASTName compName = compType.getName();
|
||||
|
@ -147,6 +148,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#addBinding(org.eclipse.cdt.core.dom.ast.IBinding)
|
||||
*/
|
||||
@Override
|
||||
public void addBinding(IBinding binding) {
|
||||
if (binding instanceof ICPPConstructor) {
|
||||
addConstructor(binding);
|
||||
|
@ -155,11 +157,16 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
super.addBinding(binding);
|
||||
}
|
||||
|
||||
public void addName(IASTName name) {
|
||||
if (name instanceof ICPPASTQualifiedName)
|
||||
return;
|
||||
|
||||
@Override
|
||||
public void addName(IASTName name) throws DOMException {
|
||||
IASTNode parent = name.getParent();
|
||||
if (name instanceof ICPPASTQualifiedName) {
|
||||
final IASTName[] qn= ((ICPPASTQualifiedName) name).getNames();
|
||||
final IASTName ln= qn[qn.length-1];
|
||||
if (CPPVisitor.getContainingScope(name) != CPPVisitor.getContainingScope(ln)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (parent instanceof IASTDeclarator) {
|
||||
if (CPPVisitor.isConstructor(this, (IASTDeclarator) parent)) {
|
||||
addConstructor(name);
|
||||
|
@ -194,6 +201,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#getBinding(int, char[])
|
||||
*/
|
||||
@Override
|
||||
public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) throws DOMException {
|
||||
char[] c = name.toCharArray();
|
||||
|
||||
|
@ -213,6 +221,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
return super.getBinding(name, resolve, fileSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) throws DOMException {
|
||||
char[] c = name.toCharArray();
|
||||
|
||||
|
@ -298,6 +307,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public IBinding[] find(String name) throws DOMException {
|
||||
char[] n = name.toCharArray();
|
||||
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
|
||||
|
@ -370,6 +380,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
|||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#removeBinding(org.eclipse.cdt.core.dom.ast.IBinding)
|
||||
*/
|
||||
@Override
|
||||
public void removeBinding(IBinding binding) {
|
||||
if (binding instanceof ICPPConstructor) {
|
||||
removeBinding(CONSTRUCTOR_KEY, binding);
|
||||
|
|
|
@ -259,7 +259,7 @@ public class CPPFunction extends PlatformObject implements ICPPFunction, ICPPInt
|
|||
return getASTName().toCharArray();
|
||||
}
|
||||
|
||||
private IASTName getASTName() {
|
||||
protected IASTName getASTName() {
|
||||
IASTDeclarator dtor = (definition != null) ? definition : declarations[0];
|
||||
IASTDeclarator nested= dtor.getNestedDeclarator();
|
||||
while (nested != null) {
|
||||
|
|
|
@ -176,32 +176,13 @@ public class CPPMethod extends CPPFunction implements ICPPMethod {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if( definition != null ){
|
||||
IASTName n = definition.getName();
|
||||
if( n instanceof ICPPASTQualifiedName ){
|
||||
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
|
||||
return ns[ ns.length - 1 ].toString();
|
||||
}
|
||||
return n.toString();
|
||||
protected IASTName getASTName() {
|
||||
IASTName name= definition != null ? definition.getName() : declarations[0].getName();
|
||||
if( name instanceof ICPPASTQualifiedName ){
|
||||
final IASTName[] ns = ((ICPPASTQualifiedName)name).getNames();
|
||||
return ns[ns.length - 1];
|
||||
}
|
||||
return declarations[0].getName().toString();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.core.dom.ast.IBinding#getNameCharArray()
|
||||
*/
|
||||
@Override
|
||||
public char[] getNameCharArray() {
|
||||
if( definition != null ){
|
||||
IASTName n = definition.getName();
|
||||
if( n instanceof ICPPASTQualifiedName ){
|
||||
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
|
||||
return ns[ ns.length - 1 ].toCharArray();
|
||||
}
|
||||
return n.toCharArray();
|
||||
}
|
||||
return declarations[0].getName().toCharArray();
|
||||
return name;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IScope;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
|
@ -73,14 +74,25 @@ abstract public class CPPScope implements ICPPScope, IASTInternalScope {
|
|||
|
||||
protected CharArrayObjectMap bindings = null;
|
||||
|
||||
public void addName(IASTName name) {
|
||||
public void addName(IASTName name) throws DOMException {
|
||||
if( bindings == null )
|
||||
bindings = new CharArrayObjectMap(1);
|
||||
if( name instanceof ICPPASTQualifiedName ){
|
||||
//name belongs to a different scope, don't add it here
|
||||
return;
|
||||
char[] c;
|
||||
if (name instanceof ICPPASTQualifiedName) {
|
||||
if (physicalNode instanceof ICPPASTCompositeTypeSpecifier == false &&
|
||||
physicalNode instanceof ICPPASTNamespaceDefinition == false)
|
||||
return;
|
||||
|
||||
//name belongs to a different scope, don't add it here except it names this scope
|
||||
final IASTName[] ns= ((ICPPASTQualifiedName) name).getNames();
|
||||
final IASTName ln= ns[ns.length-1];
|
||||
if (CPPVisitor.getContainingScope(name) != CPPVisitor.getContainingScope(ln))
|
||||
return;
|
||||
c= ln.toCharArray();
|
||||
}
|
||||
else {
|
||||
c= name.toCharArray();
|
||||
}
|
||||
char [] c = name.toCharArray();
|
||||
Object o = bindings.get( c );
|
||||
if( o != null ){
|
||||
if( o instanceof ObjectSet ){
|
||||
|
|
|
@ -1485,7 +1485,7 @@ public class CPPSemantics {
|
|||
|
||||
//9-2 a class name is also inserted into the scope of the class itself
|
||||
IASTName n = comp.getName();
|
||||
if( nameMatches( data, n ) ) {
|
||||
if( nameMatches( data, n, scope) ) {
|
||||
found = (IASTName[]) ArrayUtil.append( IASTName.class, found, n );
|
||||
}
|
||||
} else if ( parent instanceof ICPPASTNamespaceDefinition ){
|
||||
|
@ -1716,14 +1716,14 @@ public class CPPSemantics {
|
|||
dtor = dtor.getNestedDeclarator();
|
||||
IASTName declName = dtor.getName();
|
||||
ASTInternal.addName( scope, declName );
|
||||
if( !data.typesOnly && nameMatches( data, declName ) ) {
|
||||
if( !data.typesOnly && nameMatches( data, declName, scope ) ) {
|
||||
return declName;
|
||||
}
|
||||
}
|
||||
} else if( node instanceof ICPPASTTemplateParameter ){
|
||||
IASTName name = CPPTemplates.getTemplateParameterName( (ICPPASTTemplateParameter) node );
|
||||
ASTInternal.addName( scope, name );
|
||||
if( nameMatches( data, name ) ) {
|
||||
if( nameMatches( data, name, scope ) ) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
@ -1742,7 +1742,7 @@ public class CPPSemantics {
|
|||
IASTName declaratorName = declarator.getName();
|
||||
ASTInternal.addName( scope, declaratorName );
|
||||
if( !data.typesOnly || simpleDeclaration.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ) {
|
||||
if( nameMatches( data, declaratorName ) ) {
|
||||
if( nameMatches( data, declaratorName, scope ) ) {
|
||||
if( resultName == null )
|
||||
resultName = declaratorName;
|
||||
else if( resultArray == null )
|
||||
|
@ -1805,7 +1805,7 @@ public class CPPSemantics {
|
|||
if( enumerator == null ) break;
|
||||
tempName = enumerator.getName();
|
||||
ASTInternal.addName( scope, tempName );
|
||||
if( !data.typesOnly && nameMatches( data, tempName ) ) {
|
||||
if( !data.typesOnly && nameMatches( data, tempName, scope ) ) {
|
||||
if( resultName == null )
|
||||
resultName = tempName;
|
||||
else if( resultArray == null )
|
||||
|
@ -1817,7 +1817,7 @@ public class CPPSemantics {
|
|||
}
|
||||
if( specName != null ) {
|
||||
ASTInternal.addName( scope, specName );
|
||||
if( nameMatches( data, specName ) ) {
|
||||
if( nameMatches( data, specName, scope ) ) {
|
||||
if( resultName == null )
|
||||
resultName = specName;
|
||||
else if( resultArray == null )
|
||||
|
@ -1834,18 +1834,18 @@ public class CPPSemantics {
|
|||
name = ns[ ns.length - 1 ];
|
||||
}
|
||||
ASTInternal.addName( scope, name );
|
||||
if( nameMatches( data, name ) ) {
|
||||
if( nameMatches( data, name, scope ) ) {
|
||||
return name;
|
||||
}
|
||||
} else if( declaration instanceof ICPPASTNamespaceDefinition ){
|
||||
IASTName namespaceName = ((ICPPASTNamespaceDefinition) declaration).getName();
|
||||
ASTInternal.addName( scope, namespaceName );
|
||||
if( nameMatches( data, namespaceName ) )
|
||||
if( nameMatches( data, namespaceName, scope ) )
|
||||
return namespaceName;
|
||||
} else if( declaration instanceof ICPPASTNamespaceAlias ){
|
||||
IASTName alias = ((ICPPASTNamespaceAlias) declaration).getAlias();
|
||||
ASTInternal.addName( scope, alias );
|
||||
if( nameMatches( data, alias ) )
|
||||
if( nameMatches( data, alias, scope ) )
|
||||
return alias;
|
||||
} else if( declaration instanceof IASTFunctionDefinition ){
|
||||
IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration;
|
||||
|
@ -1856,7 +1856,7 @@ public class CPPSemantics {
|
|||
IASTName declName = declarator.getName();
|
||||
ASTInternal.addName( scope, declName );
|
||||
|
||||
if( !data.typesOnly && nameMatches( data, declName ) ) {
|
||||
if( !data.typesOnly && nameMatches( data, declName, scope ) ) {
|
||||
return declName;
|
||||
}
|
||||
}
|
||||
|
@ -1867,11 +1867,20 @@ public class CPPSemantics {
|
|||
return resultName;
|
||||
}
|
||||
|
||||
private static final boolean nameMatches( LookupData data, IASTName potential ){
|
||||
private static final boolean nameMatches( LookupData data, IASTName potential, IScope scope) throws DOMException{
|
||||
if( potential instanceof ICPPASTQualifiedName ){
|
||||
IASTNode phn= ASTInternal.getPhysicalNodeOfScope(scope);
|
||||
if (phn instanceof ICPPASTCompositeTypeSpecifier == false && phn instanceof ICPPASTNamespaceDefinition == false)
|
||||
return false;
|
||||
|
||||
//A qualified name implies the name actually belongs to a different scope, and should
|
||||
//not be considered here.
|
||||
return false;
|
||||
//not be considered here, except the qualifier names the scope itself
|
||||
final IASTName[] qn= ((ICPPASTQualifiedName) potential).getNames();
|
||||
final IASTName ln= qn[qn.length-1];
|
||||
if (CPPVisitor.getContainingScope(ln) != scope)
|
||||
return false;
|
||||
|
||||
potential= ln;
|
||||
}
|
||||
char[] c = potential.toCharArray();
|
||||
char [] n = data.name();
|
||||
|
|
|
@ -167,16 +167,21 @@ public class CPPVisitor {
|
|||
if( binding instanceof IProblemBinding && parent instanceof ICPPASTQualifiedName
|
||||
&& !(parent.getParent() instanceof ICPPASTNamespaceAlias))
|
||||
{
|
||||
if( ((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND ){
|
||||
final ICPPASTQualifiedName qname= (ICPPASTQualifiedName)parent;
|
||||
final IASTName[] ns= qname.getNames();
|
||||
if (ns[ns.length-1] != name)
|
||||
return binding;
|
||||
|
||||
parent = parent.getParent();
|
||||
if( ((IProblemBinding)binding).getID() == IProblemBinding.SEMANTIC_MEMBER_DECLARATION_NOT_FOUND ){
|
||||
IASTNode node = getContainingBlockItem( name.getParent() );
|
||||
if( node.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION )
|
||||
ASTNodeProperty prop= node.getPropertyInParent();
|
||||
if (prop != IASTCompositeTypeSpecifier.MEMBER_DECLARATION && prop != ICPPASTNamespaceDefinition.OWNED_DECLARATION)
|
||||
return binding;
|
||||
|
||||
if (getContainingScope(qname) != getContainingScope(name))
|
||||
return binding;
|
||||
}
|
||||
IASTName [] ns = ((ICPPASTQualifiedName)parent).getNames();
|
||||
if( ns[ ns.length - 1 ] == name )
|
||||
parent = parent.getParent();
|
||||
else
|
||||
return binding;
|
||||
} else {
|
||||
return binding;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ package org.eclipse.cdt.internal.core.dom.rewrite.changegenerator;
|
|||
import org.eclipse.osgi.util.NLS;
|
||||
|
||||
/**
|
||||
* mstodo
|
||||
*
|
||||
* External strings for the change generator.
|
||||
* @since 5.0
|
||||
*/
|
||||
public class Messages extends NLS {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Symbian Software Systems and others.
|
||||
* Copyright (c) 2007, 2008 Symbian Software Systems and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Andrew Ferguson (Symbian) - Initial implementation
|
||||
* Bryan Wilkinson (QNX)
|
||||
* Andrew Ferguson (Symbian) - Initial implementation
|
||||
* Bryan Wilkinson (QNX)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.index.composite.cpp;
|
||||
|
||||
|
@ -44,7 +44,8 @@ public class TemplateInstanceUtil {
|
|||
if(specd instanceof ICPPTemplateDefinition) {
|
||||
keysToAdapt= ((ICPPTemplateDefinition)specd).getTemplateParameters();
|
||||
}
|
||||
for(int i=0; i<keys.length; i++) {
|
||||
final int length= Math.min(keys.length, keysToAdapt.length);
|
||||
for(int i=0; i<length; i++) {
|
||||
IType type= (IType) preresult.get(keys[i]);
|
||||
result.put(
|
||||
cf.getCompositeBinding((IIndexFragmentBinding)keysToAdapt[i]),
|
||||
|
|
Loading…
Add table
Reference in a new issue