From b4309ac47a9deba5c7454c870c22f214ff51b073 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Tue, 24 Feb 2004 22:09:59 +0000 Subject: [PATCH] Start of bug 51485: PST Templates: Explicit Specialization --- core/org.eclipse.cdt.core.tests/ChangeLog | 7 + .../tests/ParserSymbolTableTemplateTests.java | 214 +++++++++++++++++- .../parser/ChangeLog-parser | 4 + .../core/parser/pst/ContainerSymbol.java | 49 +++- .../core/parser/pst/ITemplateSymbol.java | 6 +- .../core/parser/pst/TemplateEngine.java | 135 ++++++++--- .../core/parser/pst/TemplateFactory.java | 68 +++++- .../core/parser/pst/TemplateSymbol.java | 60 ++++- 8 files changed, 488 insertions(+), 55 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index 72e58eef948..5df4533e2b4 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,10 @@ +2004-02-24 Andrew Niefer + work for Bug 51485: Template Explicit Specializations + added ParserSymbolTableTemplateTests.test_14_7_3__5_ExplicitSpecialization + added ParserSymbolTableTemplateTests.test_14_7_3__11_ExplicitSpecializationArgumentDeduction + added ParserSymbolTableTemplateTests.test_14_7_3__12_ExplicitSpecializationOverloadedFunction + fixed a couple of warnings in ParserSymbolTableTemplateTests + 2004-02-23 Alain Magloire Adjust the test for IPathEntry deltas. diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java index 2d3a2f2fd6f..7c6c609e577 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java @@ -485,12 +485,10 @@ public class ParserSymbolTableTemplateTests extends TestCase { IDerivableContainerSymbol S = table.newDerivableContainerSymbol( "S", TypeInfo.t_struct ); f.addSymbol( S ); - ISymbol look = null; - List args = new LinkedList(); args.add( new TypeInfo( TypeInfo.t_type, 0, S ) ); try{ - look = f.lookupTemplate( "X", args ); + f.lookupTemplate( "X", args ); assertTrue( false ); } catch( ParserSymbolTableException e ){ assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); @@ -499,7 +497,7 @@ public class ParserSymbolTableTemplateTests extends TestCase { args.clear(); args.add( new TypeInfo( TypeInfo.t_type, 0, S, new PtrOp( PtrOp.t_pointer ), false ) ); try{ - look = f.lookupTemplate( "X", args ); + f.lookupTemplate( "X", args ); assertTrue( false ); } catch( ParserSymbolTableException e ){ assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); @@ -1620,7 +1618,7 @@ public class ParserSymbolTableTemplateTests extends TestCase { TypeInfo type = (TypeInfo) iter.next(); assertTrue( type.isType( TypeInfo.t_int ) ); } - + /** * A template-parameter shall not be redeclared within its scope. A template-parameter shall * not have the same name as the template name. @@ -1636,7 +1634,7 @@ public class ParserSymbolTableTemplateTests extends TestCase { * * @throws Exception */ - public void test_14_6_1__4_ParameterRedeclaration() throws Exception{ + public void test_14_6_1__4_ParameterRedeclaration() throws Exception{ newTable(); ITemplateSymbol template = table.newTemplateSymbol( "Y" ); @@ -1676,8 +1674,212 @@ public class ParserSymbolTableTemplateTests extends TestCase { assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateParameter ); } } + + + /** + * A member of an explicitly specialized class shall be explicitly defined in the same + * manner as members of normal classes + * + * template< class T > struct A { + * void f( T ) {} + * }; + * + * template <> struct A< int >{ + * void f( int ); + * } + * + * void A< int >::f( int ){ } + * + * @throws Exception + */ + public void test_14_7_3__5_ExplicitSpecialization() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + template.addSymbol( A ); + + table.getCompilationUnit().addSymbol( template ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f.addParameter( T, 0, null, false ); + + A.addSymbol( f ); + + LinkedList params = new LinkedList(), args = new LinkedList(); + + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + + IDerivableContainerSymbol ASpec = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + ASpec.setIsTemplateMember( true ); + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.addParameter( TypeInfo.t_int, 0, null, false ); + f2.setIsForwardDeclaration( true ); + ASpec.addSymbol( f2 ); + + factory.addSymbol( ASpec ); + + IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.addParameter( TypeInfo.t_int, 0, null, false ); + + IDerivableContainerSymbol look = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), ASpec ); + + + ISymbol flook = look.lookupMethodForDefinition( "f", args ); + assertTrue( flook.isTemplateInstance() ); + assertEquals( flook.getInstantiatedSymbol(), f2 ); + flook.setTypeSymbol( f3 ); + + look.addSymbol( f3 ); + + + look = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + flook = look.qualifiedFunctionLookup( "f", args ); + + assertEquals( flook, f3 ); + + } + /** + * template < class T > class Array { }; + * template < class T > void sort( Array< T > & ); + * + * template<> void sort( Array< int > & ){} //T deduced as int + * + * @throws Exception + */ + public void test_14_7_3__11_ExplicitSpecializationArgumentDeduction() throws Exception{ + newTable(); + + ITemplateSymbol templateArray = table.newTemplateSymbol( "Array" ); + templateArray.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol array = table.newDerivableContainerSymbol( "Array", TypeInfo.t_class ); + templateArray.addSymbol( array ); + + table.getCompilationUnit().addSymbol( templateArray ); + + ITemplateSymbol templateSort = table.newTemplateSymbol( "sort" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + templateSort.addTemplateParameter( T ); + + IParameterizedSymbol sort = table.newParameterizedSymbol( "sort", TypeInfo.t_function ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, T ) ); + ISymbol arrayLook = table.getCompilationUnit().lookupTemplate( "Array", args ); + + sort.addParameter( arrayLook, 0, new PtrOp( PtrOp.t_reference ), false ); + + templateSort.addSymbol( sort ); + + table.getCompilationUnit().addSymbol( templateSort ); + + List params = new LinkedList(); + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "sort", params, null ); + + IParameterizedSymbol newSort = table.newParameterizedSymbol( "sort", TypeInfo.t_function ); + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + arrayLook = table.getCompilationUnit().lookupTemplate( "Array", args ); + newSort.addParameter( arrayLook, 0, new PtrOp( PtrOp.t_reference ), false ); + + factory.addSymbol( newSort ); + + ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); + a.setTypeSymbol( arrayLook ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, a ) ); + + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "sort", args ); + + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), newSort ); + } + /** + * It is possible for a specialization with a given function signature to be instantiated from more + * than one function-template. In such cases, explicit specification of the template arguments must be used + * to uniquely identify the function template specialization being specialized + * + * template< class T > void f( T ); + * template< class T > void f( T * ); + * + * template <> void f( int * ); //ambiguous + * template <> void f< int >( int * ); //OK + * template <> void f( char ); //OK + * + * @throws Exception + */ + public void test_14_7_3__12_ExplicitSpecializationOverloadedFunction() throws Exception{ + newTable(); + + ITemplateSymbol template1 = table.newTemplateSymbol( "f" ); + ISymbol T1 = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template1.addTemplateParameter( T1 ); + + IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f1.addParameter( T1, 0, null, false ); + + template1.addSymbol( f1 ); + + table.getCompilationUnit().addSymbol( template1 ); + + ITemplateSymbol template2 = table.newTemplateSymbol( "f" ); + ISymbol T2 = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template2.addTemplateParameter( T2 ); + + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.addParameter( T2, 0, new PtrOp( PtrOp.t_pointer ), false ); + + template2.addSymbol( f2 ); + table.getCompilationUnit().addSymbol( template2 ); + + List params = new LinkedList(); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "f", params, null ); + + IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.addParameter( TypeInfo.t_int, 0, new PtrOp( PtrOp.t_pointer ), false ); + + try{ + factory.addSymbol( f3 ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); + } + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "f", params, args ); + IParameterizedSymbol f4 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f4.addParameter( TypeInfo.t_int, 0, new PtrOp( PtrOp.t_pointer ), false ); + factory.addSymbol( f4 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + + factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "f", params, args ); + IParameterizedSymbol f5 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f5.addParameter( TypeInfo.t_char, 0, null, false ); + factory.addSymbol( f5 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f5 ); + } + /** * template < class T > void f( T x, T y ) { } diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 6528586bf13..090b2fb29b2 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,7 @@ +2004-02-24 Andrew Niefer + Template Explicit Specializations (bug 51485) + adding basic symbol table functionality for non-nested template specializations + 2004-02-24 John Camelon Fixed https://bugs.eclipse.org/bugs/show_bug.cgi?id=52823 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java index 3de0cf6e626..44dec46dd55 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java @@ -93,6 +93,18 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { continue; } + if( !template.getExplicitSpecializations().isEmpty() ){ + List argList = new LinkedList(); + Iterator templateParams = template.getParameterList().iterator(); + while( templateParams.hasNext() ){ + argList.add( argMap.get( templateParams.next() ) ); + } + + ISymbol temp = TemplateEngine.checkForTemplateExplicitSpecialization( template, symbol, argList ); + if( temp != null ) + containedSymbol = temp; + } + Map instanceMap = argMap; if( template.getDefinitionParameterMap() != null && template.getDefinitionParameterMap().containsKey( containedSymbol ) ) @@ -727,14 +739,41 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { LookupData data = new LookupData( name, TypeInfo.t_any ); ParserSymbolTable.lookup( data, this ); - ISymbol look = ParserSymbolTable.resolveAmbiguities( data ); - if( look instanceof ITemplateSymbol ){ - ITemplateSymbol template = TemplateEngine.selectTemplateOrSpecialization( (ITemplateSymbol) look, parameters, arguments ); - if( template != null ){ - return new TemplateFactory( template, parameters ); + Object look = null; + try{ + look = ParserSymbolTable.resolveAmbiguities( data ); + } catch ( ParserSymbolTableException e ){ + if( e.reason != ParserSymbolTableException.r_UnableToResolveFunction ){ + throw e; + } + if( !data.foundItems.isEmpty() ){ + look = data.foundItems.get( name ); + if(!( look instanceof List ) ){ + throw new ParserSymbolTableError(); + } } } + + ITemplateSymbol template = (ITemplateSymbol) (( look instanceof ITemplateSymbol ) ? look : null); + if( template == null ){ + if( look instanceof ISymbol ){ + ISymbol symbol = (ISymbol) look; + if( symbol.isTemplateMember() && symbol.getContainingSymbol().isType( TypeInfo.t_template ) ){ + template = (ITemplateSymbol) symbol.getContainingSymbol(); + } + } + + } + if( template != null ){ + template = TemplateEngine.selectTemplateOrSpecialization( template, parameters, arguments ); + if( template != null ){ + return new TemplateFactory( template, parameters, arguments ); + } + } else if ( look instanceof List ){ + return new TemplateFactory( new HashSet( (List)look ), parameters, arguments ); + } + return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java index c2e541f5499..07262f394ef 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java @@ -38,12 +38,13 @@ public interface ITemplateSymbol extends IParameterizedSymbol { public Map getDefinitionParameterMap(); - public ISpecializedSymbol findSpecialization(List parameters, List arguments); public IContainerSymbol findInstantiation( List arguments ); public List findArgumentsFor( IContainerSymbol instance ); public void addInstantiation( IContainerSymbol instance, List args ); + public void addExplicitSpecialization( ISymbol symbol, List args ) throws ParserSymbolTableException; + /** * * @param args @@ -56,5 +57,6 @@ public interface ITemplateSymbol extends IParameterizedSymbol { public ISymbol instantiate( List args ) throws ParserSymbolTableException; public IDeferredTemplateInstance deferredInstance( List args ); - + + public Map getExplicitSpecializations(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java index 6466bd0f17b..3f77dba3890 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java @@ -627,7 +627,7 @@ public final class TemplateEngine { List aList = function.getParameterList(); LinkedList args = new LinkedList(); - + Iterator iter = aList.iterator(); while( iter.hasNext() ){ ISymbol symbol = (ISymbol) iter.next(); @@ -646,7 +646,7 @@ public final class TemplateEngine { * type (A), and an attempt is made to find template argument vaules that will make P, * after substitution of the deduced values, compatible with A. */ - static private Map deduceTemplateArguments( IParameterizedSymbol template, List arguments ){ + static private Map deduceTemplateArguments( ITemplateSymbol template, List arguments ){ if( template.getContainedSymbols() == null || template.getContainedSymbols().size() != 1 ){ return null; } @@ -902,18 +902,18 @@ public final class TemplateEngine { //primary definition or specialization? boolean forPrimary = true; - if( arguments != null ){ - if( !parameters.isEmpty() ){ - if( arguments.size() != parameters.size() ){ - forPrimary = false; - } else { - Iterator pIter = parameters.iterator(); - Iterator aIter = arguments.iterator(); - while( pIter.hasNext() ){ - if( pIter.next() != ((TypeInfo) aIter.next()).getTypeSymbol() ){ - forPrimary = false; - break; - } + if( parameters.size() == 0 ){ + forPrimary = false; + } else if( arguments != null ){ + if( arguments.size() != parameters.size() ){ + forPrimary = false; + } else if( !parameters.isEmpty() ){ + Iterator pIter = parameters.iterator(); + Iterator aIter = arguments.iterator(); + while( pIter.hasNext() ){ + if( pIter.next() != ((TypeInfo) aIter.next()).getTypeSymbol() ){ + forPrimary = false; + break; } } } @@ -931,21 +931,8 @@ public final class TemplateEngine { } //specialization - if( parameters.isEmpty() && !arguments.isEmpty() ){ - ISpecializedSymbol spec = primary.findSpecialization( parameters, arguments ); - - if( spec == null ){ - spec = template.getSymbolTable().newSpecializedSymbol( primary.getName() ); - - Iterator iter = arguments.iterator(); - while( iter.hasNext() ){ - spec.addArgument( (TypeInfo) iter.next() ); - } - - primary.addSpecialization( spec ); - } - - return spec; + if( parameters.isEmpty() ){ + return primary; } //partial specialization @@ -1140,4 +1127,94 @@ public final class TemplateEngine { return true; } + static protected List verifyExplicitArguments( ITemplateSymbol template, List arguments, ISymbol symbol ) throws ParserSymbolTableException{ + List actualArgs = new LinkedList(); + + Iterator params = template.getParameterList().iterator(); + Iterator args = arguments.iterator(); + + while( params.hasNext() ){ + ISymbol param = (ISymbol) params.next(); + if( args.hasNext() ){ + TypeInfo arg = (TypeInfo) args.next(); + if( matchTemplateParameterAndArgument( param, arg ) ){ + actualArgs.add( arg ); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateArgument ); + } + } else { + //14.7.3-11 a trailing template-argument can be left unspecified in the template-id naming an explicit + //function template specialization provided it can be deduced from the function argument type + if( template.getTemplatedSymbol() instanceof IParameterizedSymbol && + symbol instanceof IParameterizedSymbol && template.getTemplatedSymbol().getName().equals( symbol.getName() ) ) + { + Map map = deduceTemplateArgumentsUsingParameterList( template, (IParameterizedSymbol) symbol ); + if( map != null && map.containsKey( param ) ){ + actualArgs.add( map.get( param ) ); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateArgument ); + } + } + } + } + return actualArgs; + } + + static protected ITemplateSymbol resolveTemplateFunctions( Set functions, List args, ISymbol symbol ) throws ParserSymbolTableException{ + ITemplateSymbol template = null; + + Iterator iter = functions.iterator(); + + outer: while( iter.hasNext() ){ + IParameterizedSymbol fn = (IParameterizedSymbol) iter.next(); + ITemplateSymbol tmpl = (ITemplateSymbol) fn.getContainingSymbol(); + + Map map = deduceTemplateArgumentsUsingParameterList( tmpl, (IParameterizedSymbol) symbol ); + + if( map == null ) + continue; + else { + Iterator pIter = tmpl.getParameterList().iterator(); + Iterator aIter = args.iterator(); + while( pIter.hasNext() && aIter.hasNext() ){ + ISymbol param = (ISymbol) pIter.next(); + TypeInfo arg = (TypeInfo) aIter.next(); + if( map.containsKey( param ) ) { + if( !map.get( param ).equals( arg )){ + continue outer; + } + } else if( !matchTemplateParameterAndArgument( param, arg )){ + continue outer; + } + } + //made it this far, its a match + if( template != null ){ + throw new ParserSymbolTableException(ParserSymbolTableException.r_Ambiguous ); + } else { + template = tmpl; + } + } + } + + return template; + } + static protected ISymbol checkForTemplateExplicitSpecialization( ITemplateSymbol template, ISymbol symbol, List arguments ){ + if( !template.getExplicitSpecializations().isEmpty() ){ + //TODO: could optimize this if we had a TypeInfo.hashCode() + Iterator iter = template.getExplicitSpecializations().keySet().iterator(); + List args = null; + while( iter.hasNext() ){ + args = (List) iter.next(); + + if( args.equals( arguments ) ){ + Map explicitMap = (Map) template.getExplicitSpecializations().get( args ); + if( explicitMap.containsKey( symbol ) ){ + return (ISymbol) explicitMap.get( symbol ); + } + } + } + } + + return null; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java index e1ab2ae1d74..3cbb52d0aac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java @@ -24,17 +24,32 @@ import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.LookupData; */ public class TemplateFactory implements ITemplateFactory { - protected TemplateFactory( ITemplateSymbol primary, List params ){ + protected TemplateFactory( ITemplateSymbol primary, List params, List args ){ templatesList = new LinkedList(); templatesList.add( primary ); parametersList = new LinkedList(); parametersList.add( new LinkedList( params ) ); + + argumentsList = new LinkedList(); + argumentsList.add( args != null ? new LinkedList( args ) : new LinkedList() ); } - protected TemplateFactory( List templates, List params ){ - templatesList = templates; - parametersList = params; + protected TemplateFactory( List templates, List params, List args ){ + templatesList = templates; + parametersList = params; + argumentsList = args; + } + + protected TemplateFactory( Set functions, List params, List args ){ + templatesList = new LinkedList(); + templateFunctions = functions; + + parametersList = new LinkedList(); + parametersList.add( new LinkedList( params ) ); + + argumentsList = new LinkedList(); + argumentsList.add( args != null ? new LinkedList( args ) : new LinkedList() ); } public ITemplateFactory lookupTemplateForMemberDefinition( String name, List parameters, List arguments ) throws ParserSymbolTableException{ @@ -55,11 +70,13 @@ public class TemplateFactory implements ITemplateFactory { if( template != null ){ List newTemplatesList = new LinkedList( templatesList ); List newParamsList = new LinkedList( parametersList ); + List newArgsList = new LinkedList( argumentsList ); newTemplatesList.add( template ); newParamsList.add( new LinkedList( parameters ) ); + newArgsList.add( arguments != null ? new LinkedList( arguments ) : new LinkedList() ); - return new TemplateFactory( newTemplatesList, newParamsList ); + return new TemplateFactory( newTemplatesList, newParamsList, newArgsList ); } } @@ -70,6 +87,11 @@ public class TemplateFactory implements ITemplateFactory { * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#addSymbol(org.eclipse.cdt.internal.core.parser.pst.ISymbol) */ public void addSymbol( ISymbol symbol ) throws ParserSymbolTableException { + if( ((List)getParametersList().get( 0 )).isEmpty() ){ + addExplicitSpecialization( symbol ); + return; + } + Iterator templatesIter = getTemplatesList().iterator(); Iterator parametersIter = getParametersList().iterator(); @@ -106,10 +128,34 @@ public class TemplateFactory implements ITemplateFactory { } } + private void addExplicitSpecialization( ISymbol symbol ) throws ParserSymbolTableException { + Iterator templatesIter = getTemplatesList().iterator(); + Iterator argsIter = getArgumentsList().iterator(); + + while( templatesIter.hasNext() ){ + ITemplateSymbol template = (ITemplateSymbol)templatesIter.next(); + + template.addExplicitSpecialization( symbol, (List) argsIter.next() ); + } + + if( getTemplateFunctions() != null && argsIter.hasNext() ){ + List args = (List) argsIter.next(); + ITemplateSymbol template = TemplateEngine.resolveTemplateFunctions( getTemplateFunctions(), args, symbol ); + if( template != null ){ + template.addExplicitSpecialization( symbol, args ); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); + } + } + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#lookupMemberForDefinition(java.lang.String) */ public ISymbol lookupMemberForDefinition(String name) throws ParserSymbolTableException { + if( getTemplateFunctions() != null ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); + } Set keys = getPrimaryTemplate().getContainedSymbols().keySet(); IContainerSymbol symbol = (IContainerSymbol) getPrimaryTemplate().getContainedSymbols().get( keys.iterator().next() ); @@ -120,6 +166,10 @@ public class TemplateFactory implements ITemplateFactory { * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#lookupMemberFunctionForDefinition(java.lang.String, java.util.List) */ public IParameterizedSymbol lookupMemberFunctionForDefinition( String name, List params) throws ParserSymbolTableException { + if( getTemplateFunctions() != null ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); + } + Set keys = getPrimaryTemplate().getContainedSymbols().keySet(); IContainerSymbol symbol = (IContainerSymbol) getPrimaryTemplate().getContainedSymbols().get( keys.iterator().next() ); @@ -157,7 +207,15 @@ public class TemplateFactory implements ITemplateFactory { protected List getParametersList() { return parametersList; } + protected List getArgumentsList(){ + return argumentsList; + } + protected Set getTemplateFunctions(){ + return templateFunctions; + } + private Set templateFunctions; private List templatesList; private List parametersList; + private List argumentsList; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java index afaad47de47..490d8311667 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java @@ -147,7 +147,10 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb return deferredInstance( arguments ); } - IContainerSymbol symbol = template.getTemplatedSymbol(); + IContainerSymbol symbol = template.getTemplatedSymbol(); + ISymbol temp = TemplateEngine.checkForTemplateExplicitSpecialization( template, symbol, actualArgs ); + symbol = (IContainerSymbol) ( temp != null ? temp : symbol); + instance = (IContainerSymbol) symbol.instantiate( template, map ); addInstantiation( instance, actualArgs ); return instance; @@ -227,6 +230,45 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb public boolean hasSpecializations(){ return ( _specializations != null && !_specializations.isEmpty() ); } + + public void addExplicitSpecialization( ISymbol symbol, List args ) throws ParserSymbolTableException{ + + List actualArgs = TemplateEngine.verifyExplicitArguments( this, args, symbol ); + + Map map = getExplicitSpecializations(); + + Map specs = null; + if( map.containsKey( actualArgs ) ){ + specs = (Map) map.get( actualArgs ); + } else { + specs = new HashMap(); + map.put( new LinkedList( actualArgs ), specs ); + } + + ISymbol found = null; + try{ + if( symbol.isType( TypeInfo.t_function ) || symbol.isType( TypeInfo.t_constructor ) ){ + List fnArgs = new LinkedList(); + Iterator iter = ((IParameterizedSymbol)symbol).getParameterList().iterator(); + while( iter.hasNext() ){ + fnArgs.add( ((ISymbol)iter.next()).getTypeInfo() ); + } + found = getTemplatedSymbol().lookupMethodForDefinition( symbol.getName(), fnArgs ); + } else { + found = getTemplatedSymbol().lookupMemberForDefinition( symbol.getName() ); + } + } catch (ParserSymbolTableException e) { + } + if( found == null && getTemplatedSymbol().getName().equals( symbol.getName() ) ){ + found = getTemplatedSymbol(); + } + + if( found != null ){ + symbol.setIsTemplateMember( true ); + symbol.setContainingSymbol( found.getContainingSymbol() ); + specs.put( found, symbol ); + } + } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addSpecialization(org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol) @@ -304,15 +346,17 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb public IDeferredTemplateInstance deferredInstance( List args ){ return new DeferredTemplateInstance( getSymbolTable(), this, args ); } - - public ISpecializedSymbol findSpecialization(List parameters, List arguments) { - // TODO Auto-generated method stub - return null; - } + public Map getExplicitSpecializations() { + if( _explicitSpecializations == null ){ + _explicitSpecializations = new HashMap(); + } + return _explicitSpecializations; + } - private LinkedList _specializations; //template specializations - private HashMap _defnParameterMap; //members could be defined with different template parameter names + private LinkedList _specializations; //template specializations + private HashMap _explicitSpecializations; //explicit specializations + private HashMap _defnParameterMap; //members could be defined with different template parameter names private HashMap _instantiations; } \ No newline at end of file