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 d43e81405fa..ca708da7e2d 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 @@ -4822,4 +4822,28 @@ public class AST2CPPTests extends AST2BaseTest { IFunction free = (IFunction) col.getName(0).resolveBinding(); assertSame( free, col.getName(4).resolveBinding() ); } + + public void testBug86688() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("class X; \n"); + buffer.append("void f() { \n"); + buffer.append(" class A { \n"); + buffer.append(" friend class X; \n"); + buffer.append(" }; \n"); + buffer.append("} \n"); + buffer.append("namespace B { \n"); + buffer.append(" class A { \n"); + buffer.append(" friend class X; \n"); + buffer.append(" }; \n"); + buffer.append("} \n"); + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP, true, true ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPClassType X = (ICPPClassType) col.getName(0).resolveBinding(); + assertNotSame( X, col.getName(3).resolveBinding() ); + assertTrue( col.getName(3).resolveBinding() instanceof ICPPClassType ); + assertSame( X, col.getName(6).resolveBinding() ); + } } 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 814622c8f33..e04f136cf0f 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 @@ -382,6 +382,42 @@ public class CPPSemantics { } return implied; } + public boolean forFriendship() { + if( astName == null ) + return false; + IASTNode node = astName.getParent(); + while( node instanceof IASTName ) + node = node.getParent(); + + IASTDeclaration decl = null; + IASTDeclarator dtor = null; + if( node instanceof ICPPASTDeclSpecifier && node.getParent() instanceof IASTDeclaration ){ + decl = (IASTDeclaration) node.getParent(); + } else if( node instanceof IASTDeclarator ) { + dtor = (IASTDeclarator) node; + while( dtor.getParent() instanceof IASTDeclarator ) + dtor = (IASTDeclarator) dtor.getParent(); + if( !(dtor.getParent() instanceof IASTDeclaration) ) + return false; + decl = (IASTDeclaration) dtor.getParent(); + } else { + return false; + } + if( decl instanceof IASTSimpleDeclaration ){ + IASTSimpleDeclaration simple = (IASTSimpleDeclaration) decl; + if( ! ((ICPPASTDeclSpecifier)simple.getDeclSpecifier()).isFriend() ) + return false; + if( dtor != null ) + return true; + return simple.getDeclarators().length == 0; + } else if( decl instanceof IASTFunctionDefinition ){ + IASTFunctionDefinition fnDef = (IASTFunctionDefinition) decl; + if( ! ((ICPPASTDeclSpecifier)fnDef.getDeclSpecifier()).isFriend() ) + return false; + return ( dtor != null ); + } + return false; + } } static protected class Cost @@ -871,6 +907,15 @@ public class CPPSemantics { else scope = getLookupScope( (IASTName) start ); + boolean friendInLocalClass = false; + if( scope instanceof ICPPClassScope && data.forFriendship() ){ + try { + ICPPClassType cls = ((ICPPClassScope)scope).getClassType(); + friendInLocalClass = !cls.isGloballyQualified(); + } catch ( DOMException e ){ + } + } + while( scope != null ){ IASTNode blockItem = CPPVisitor.getContainingBlockItem( node ); @@ -926,8 +971,11 @@ public class CPPSemantics { } } - if( !data.prefixLookup && (data.problem != null || data.hasResults()) ) + if( (!data.prefixLookup && (data.problem != null || data.hasResults())) || + ( friendInLocalClass && !(scope instanceof ICPPClassScope) ) ) + { return; + } if( !data.usingDirectivesOnly && scope instanceof ICPPClassScope ){ mergeResults( data, lookupInParents( data, scope ), true );