From 15e4fa6b791795510b9d00048baf5d7e12f82c13 Mon Sep 17 00:00:00 2001 From: John Camelon Date: Thu, 8 Jan 2004 16:57:54 +0000 Subject: [PATCH] Patch for Andrew Niefer Core: Added IDerivableContainerSymbol.lookupFunctionForFriendship. Modified IASTFactory.createMethod to take an ITokenDuple for the method name. Added LookupType.FORFRIENDSHIP and use it in LookupElement. Modified CompleteParseASTFactory.createMethod to handle friend functions. Tests: Added CompleteParseASTTest::testBug48307_FriendFunction_1 Added CompleteParseASTTest::testBug48307_FriendFunction_2 --- core/org.eclipse.cdt.core.tests/ChangeLog | 4 ++ .../parser/tests/CompleteParseASTTest.java | 46 +++++++++++++ .../parser/ChangeLog-parser | 7 ++ .../cdt/core/parser/ast/IASTFactory.java | 2 +- .../core/parser/DeclarationWrapper.java | 2 +- .../ast/complete/CompleteParseASTFactory.java | 64 ++++++++++++++----- .../ast/quick/QuickParseASTFactory.java | 4 +- .../parser/pst/DerivableContainerSymbol.java | 19 ++++++ .../parser/pst/IDerivableContainerSymbol.java | 2 + 9 files changed, 129 insertions(+), 21 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index d64b4c88b4c..eb29797122d 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,7 @@ +2004-01-08 Andrew Niefer + Added CompleteParseASTTest::testBug48307_FriendFunction_1 + Added CompleteParseASTTest::testBug48307_FriendFunction_2 + 2004-01-06 Andrew Niefer Added ContextualParseTest::testCompletionLookup_LookupKindTHIS diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java index 6ea8cc3d3f5..6d0040c229e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.java @@ -32,6 +32,7 @@ import org.eclipse.cdt.core.parser.ast.IASTFunction; import org.eclipse.cdt.core.parser.ast.IASTLinkageSpecification; import org.eclipse.cdt.core.parser.ast.IASTMethod; import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; +import org.eclipse.cdt.core.parser.ast.IASTNode; import org.eclipse.cdt.core.parser.ast.IASTParameterDeclaration; import org.eclipse.cdt.core.parser.ast.IASTReference; import org.eclipse.cdt.core.parser.ast.IASTScope; @@ -41,6 +42,7 @@ import org.eclipse.cdt.core.parser.ast.IASTUsingDeclaration; import org.eclipse.cdt.core.parser.ast.IASTUsingDirective; import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.cdt.core.parser.ast.IASTVariableReference; +import org.eclipse.cdt.core.parser.ast.IASTNode.LookupResult; import org.eclipse.cdt.internal.core.parser.ParserException; @@ -1113,4 +1115,48 @@ public class CompleteParseASTTest extends CompleteParseBaseTest while( i.hasNext() ) assertTrue( ((IASTFunction)i.next()).takesVarArgs() ); } + + public void testBug48307_FriendFunction_1() throws Exception { + StringWriter writer = new StringWriter(); + writer.write( "class A{ public : void foo(); }; " ); + writer.write( "class B{ "); + writer.write( " private : int aPrivate;" ); + writer.write( " friend void A::foo(); "); + writer.write( "};" ); + writer.write( "void A::foo(){}" ); + + Iterator i = parse( writer.toString() ).getDeclarations(); + + IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTClassSpecifier classB = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTMethod method = (IASTMethod) i.next(); + + LookupResult result = method.lookup( "a", new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, classB ); + + assertEquals( result.getResultsSize(), 1 ); + IASTField field = (IASTField) result.getNodes().next(); + assertEquals( field.getName(), "aPrivate" ); + } + + public void testBug48307_FriendFunction_2() throws Exception { + StringWriter writer = new StringWriter(); + writer.write( "void global();" ); + writer.write( "class B{ "); + writer.write( " private : int aPrivate;" ); + writer.write( " friend void global(); "); + writer.write( "};" ); + writer.write( "void global(){}" ); + + Iterator i = parse( writer.toString() ).getDeclarations(); + + IASTFunction functionDecl = (IASTFunction) i.next(); + IASTClassSpecifier classB = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTFunction functionDef = (IASTFunction) i.next(); + + LookupResult result = functionDef.lookup( "a", new IASTNode.LookupKind[] { IASTNode.LookupKind.ALL }, classB ); + + assertEquals( result.getResultsSize(), 1 ); + IASTField field = (IASTField) result.getNodes().next(); + assertEquals( field.getName(), "aPrivate" ); + } } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 735e6e9d6ea..cd353db34e3 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,10 @@ +2004-01-08 Andrew Niefer + Fixing 48307 - PST: Friendship needs to be handled better + Added IDerivableContainerSymbol.lookupFunctionForFriendship. + Modified IASTFactory.createMethod to take an ITokenDuple for the method name. + Added LookupType.FORFRIENDSHIP and use it in LookupElement. + Modified CompleteParseASTFactory.createMethod to handle friend functions. + 2004-01-06 Andrew Niefer For Content Assist, support lookup using LookupKind.THIS (lookup in the class of the this pointer ) Fix bug where forward declared method/functions appeared twice in the content assist lookup results. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTFactory.java index fce77f8eb8b..d83f69d4422 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ast/IASTFactory.java @@ -180,7 +180,7 @@ public interface IASTFactory public IASTMethod createMethod( IASTScope scope, - String name, + ITokenDuple name, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DeclarationWrapper.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DeclarationWrapper.java index ebf5b0ba9ef..0d8ccdcdfd3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DeclarationWrapper.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/DeclarationWrapper.java @@ -463,7 +463,7 @@ public class DeclarationWrapper implements IDeclaratorOwner return astFactory .createMethod( scope, - nested ? declarator.getOwnedDeclarator().getName() : declarator.getName(), + nested ? declarator.getOwnedDeclarator().getNameDuple() : declarator.getNameDuple(), createParameterList(declarator.getParameters()), astFactory.createAbstractDeclaration( constt, diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java index 8273a023005..06d1dbdb48e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/complete/CompleteParseASTFactory.java @@ -107,6 +107,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto public static final LookupType QUALIFIED = new LookupType( 1 ); public static final LookupType UNQUALIFIED = new LookupType( 2 ); public static final LookupType FORDEFINITION = new LookupType( 3 ); + public static final LookupType FORFRIENDSHIP = new LookupType( 4 ); private LookupType( int constant) { @@ -174,8 +175,11 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto result = startingScope.qualifiedFunctionLookup(name, new LinkedList(parameters)); else if( lookupType == LookupType.UNQUALIFIED ) result = startingScope.unqualifiedFunctionLookup( name, new LinkedList( parameters ) ); - else + else if( lookupType == LookupType.FORDEFINITION ) result = startingScope.lookupMethodForDefinition( name, new LinkedList( parameters ) ); + else if( lookupType == LookupType.FORFRIENDSHIP ){ + result = ((IDerivableContainerSymbol)startingScope).lookupFunctionForFriendship( name, new LinkedList( parameters) ); + } } else result = null; @@ -185,8 +189,10 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto result = startingScope.qualifiedLookup(name, type); else if( lookupType == LookupType.UNQUALIFIED ) result = startingScope.elaboratedLookup( type, name ); - else + else if( lookupType == LookupType.FORDEFINITION ) result = startingScope.lookupMemberForDefinition( name ); + else if( lookupType == LookupType.FORFRIENDSHIP ) + result = ((IDerivableContainerSymbol)startingScope).lookupForFriendship( name ); } } catch (ParserSymbolTableException e) { if( e.reason != ParserSymbolTableException.r_UnableToResolveFunction ) @@ -1622,7 +1628,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto name.length() - 1 ); return createMethod( methodParentScope, - newName.toString(), + newName, parameters, returnType, exception, @@ -1876,7 +1882,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto public IASTMethod createMethod( IASTScope scope, - String name, + ITokenDuple name, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, @@ -1902,7 +1908,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto public IASTMethod createMethod( IASTScope scope, - String name, + ITokenDuple nameDuple, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, @@ -1926,7 +1932,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto boolean isDestructor = false; IContainerSymbol ownerScope = scopeToSymbol( scope ); - IParameterizedSymbol symbol = pst.newParameterizedSymbol( name, TypeInfo.t_function ); + IParameterizedSymbol symbol = pst.newParameterizedSymbol( nameDuple.toString(), TypeInfo.t_function ); setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol); setMethodTypeInfoBits( symbol, isConst, isVolatile, isVirtual, isExplicit ); if(references == null) @@ -1943,9 +1949,9 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto if(parentName.indexOf(DOUBLE_COLON) != -1){ parentName = parentName.substring(parentName.lastIndexOf(DOUBLE_COLON) + DOUBLE_COLON.length()); } - if( parentName.equals(name) ){ + if( parentName.equals(nameDuple.toString()) ){ isConstructor = true; - } else if(name.startsWith(TELTA) && parentName.equals(name.substring(1))){ + } else if(nameDuple.getFirstToken().getType() == IToken.tCOMPL && parentName.equals(nameDuple.getLastToken().getImage())){ isDestructor = true; } } @@ -1953,7 +1959,9 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto symbol.setIsForwardDeclaration(!isFunctionDefinition); boolean previouslyDeclared = false; - if( isFunctionDefinition ) + IParameterizedSymbol functionDeclaration = null; + + if( isFunctionDefinition || isFriend ) { List functionParameters = new LinkedList(); // the lookup requires a list of type infos @@ -1964,15 +1972,34 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto functionParameters.add(param.getSymbol().getTypeInfo()); } - IParameterizedSymbol functionDeclaration = null; - List functionReferences = new ArrayList(); - functionDeclaration = - (IParameterizedSymbol) lookupQualifiedName(ownerScope, name, isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, functionParameters, 0, functionReferences, false, LookupType.FORDEFINITION ); - - if( functionDeclaration != null ) + + if( isFriend ) + { + functionDeclaration = + (IParameterizedSymbol) lookupQualifiedName(ownerScope, nameDuple, isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, functionParameters, functionReferences, false, LookupType.FORFRIENDSHIP ); + } else { + functionDeclaration = + (IParameterizedSymbol) lookupQualifiedName(ownerScope, nameDuple.toString(), isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, functionParameters, 0, functionReferences, false, LookupType.FORDEFINITION ); + } + + previouslyDeclared = ( functionDeclaration != null ); + + if( isFriend ) + { + if( functionDeclaration != null ) + { + symbol.setTypeSymbol( functionDeclaration ); + // friend declaration, has no real visibility, set private + visibility = ASTAccessVisibility.PRIVATE; + } else + { + //for a friend function declaration, if there is no prior declaration, the program is illformed + throw new ASTSemanticException(); + } + + } else if( functionDeclaration != null ) { - previouslyDeclared = true; functionDeclaration.setTypeSymbol( symbol ); // set the definition visibility = declaration visibility ASTMethodReference reference = (ASTMethodReference) functionReferences.iterator().next(); @@ -1982,7 +2009,10 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto try { - if( !isConstructor ) + if( isFriend ) + { + ((IDerivableContainerSymbol)ownerScope).addFriend( functionDeclaration ); + } else if( !isConstructor ) ownerScope.addSymbol( symbol ); else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/quick/QuickParseASTFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/quick/QuickParseASTFactory.java index b054ba4f444..c2cce2f696e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/quick/QuickParseASTFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ast/quick/QuickParseASTFactory.java @@ -193,9 +193,9 @@ public class QuickParseASTFactory extends BaseASTFactory implements IASTFactory /* (non-Javadoc) * @see org.eclipse.cdt.core.parser.ast.IASTFactory#createMethod(org.eclipse.cdt.core.parser.ast.IASTScope, java.lang.String, java.util.List, org.eclipse.cdt.core.parser.ast.IASTAbstractDeclaration, org.eclipse.cdt.core.parser.ast.IASTExceptionSpecification, boolean, boolean, boolean, int, int, org.eclipse.cdt.core.parser.ast.IASTTemplateDeclaration, boolean, boolean, boolean, boolean, boolean, boolean, boolean, org.eclipse.cdt.core.parser.ast.ASTAccessVisibility) */ - public IASTMethod createMethod(IASTScope scope, String name, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, boolean isInline, boolean isFriend, boolean isStatic, int startOffset, int nameOffset, int nameEndOffset, IASTTemplate ownerTemplate, boolean isConst, boolean isVolatile, boolean isVirtual, boolean isExplicit, boolean isPureVirtual, ASTAccessVisibility visibility, List constructorChain, boolean isFunctionDefinition, boolean hasFunctionTryBlock, boolean hasVariableArguments ) + public IASTMethod createMethod(IASTScope scope, ITokenDuple name, List parameters, IASTAbstractDeclaration returnType, IASTExceptionSpecification exception, boolean isInline, boolean isFriend, boolean isStatic, int startOffset, int nameOffset, int nameEndOffset, IASTTemplate ownerTemplate, boolean isConst, boolean isVolatile, boolean isVirtual, boolean isExplicit, boolean isPureVirtual, ASTAccessVisibility visibility, List constructorChain, boolean isFunctionDefinition, boolean hasFunctionTryBlock, boolean hasVariableArguments ) { - return new ASTMethod(scope, name, nameEndOffset, parameters, returnType, exception, isInline, isFriend, isStatic, startOffset, nameOffset, ownerTemplate, isConst, isVolatile, false, false, isVirtual, isExplicit, isPureVirtual, visibility, constructorChain, hasFunctionTryBlock, hasVariableArguments); + return new ASTMethod(scope, name.toString(), nameEndOffset, parameters, returnType, exception, isInline, isFriend, isStatic, startOffset, nameOffset, ownerTemplate, isConst, isVolatile, false, false, isVirtual, isExplicit, isPureVirtual, visibility, constructorChain, hasFunctionTryBlock, hasVariableArguments); } /* (non-Javadoc) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java index ddd29ad293e..003b9830f7c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java @@ -287,6 +287,25 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva return ParserSymbolTable.resolveAmbiguities( data ); } + public IParameterizedSymbol lookupFunctionForFriendship( String name, List parameters ) throws ParserSymbolTableException{ + LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + + data.parameters = parameters; + + IContainerSymbol enclosing = getContainingSymbol(); + if( enclosing != null && enclosing.isType( TypeInfo.t_namespace, TypeInfo.t_union ) ){ + while( enclosing != null && ( enclosing.getType() != TypeInfo.t_namespace) ) + { + enclosing = enclosing.getContainingSymbol(); + } + } + data.stopAt = enclosing; + + ParserSymbolTable.lookup( data, this ); + return (IParameterizedSymbol) ParserSymbolTable.resolveAmbiguities( data ); + } + + public List getFriends(){ if( _friends == null ){ _friends = new LinkedList(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java index 6eb6d9b1f26..985acc6bd73 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java @@ -40,6 +40,8 @@ public interface IDerivableContainerSymbol extends IContainerSymbol { public void addFriend( ISymbol friend ) throws ParserSymbolTableException; public ISymbol lookupForFriendship( String name ) throws ParserSymbolTableException; + public IParameterizedSymbol lookupFunctionForFriendship( String name, List parameters ) throws ParserSymbolTableException; + public List getFriends(); public interface IParentSymbol{