diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTemplateTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTemplateTest.java index 127e99e5adb..34eae7925f2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTemplateTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTemplateTest.java @@ -889,4 +889,38 @@ public class CompleteParseASTTemplateTest extends CompleteParseBaseTest { assertReferenceTask( new Task( f2, 1, false, false ) ); assertReferenceTask( new Task( f3, 1, false, false ) ); } + + public void test_14_5_2__2_MemberFunctionTemplates() throws Exception{ + Writer writer = new StringWriter(); + writer.write("template < class T > struct A { "); + writer.write(" void f( int ); "); + writer.write(" template < class T2 > void f( T2 ); "); + writer.write("}; "); + + writer.write("template <> void A::f(int) {} //non-template member \n"); + writer.write("template <> template<> void A::f<>( int ) {} //template member \n"); + + writer.write("int main(){ "); + writer.write(" A< int > ac; "); + writer.write(" ac.f( 1 ); //non-template \n"); + writer.write(" ac.f( 'c' ); //template \n"); + writer.write(" ac.f<>(1); //template \n"); + writer.write("} "); + + Iterator i = parse( writer.toString() ).getDeclarations(); + + IASTTemplateDeclaration template = (IASTTemplateDeclaration) i.next(); + IASTTemplateDeclaration spec1 = (IASTTemplateDeclaration) i.next(); + IASTTemplateDeclaration spec2 = (IASTTemplateDeclaration) i.next(); + + IASTMethod f1 = (IASTMethod) spec1.getOwnedDeclaration(); + IASTMethod f2 = (IASTMethod) spec2.getOwnedDeclaration();; + + IASTFunction main = (IASTFunction) i.next(); + assertFalse( i.hasNext() ); + + assertReferenceTask( new Task( f1, 1, false, false ) ); + //we aren't going to be completely correct about references to explicit specializations + //due to limitations in the implementation, see bug 59811 + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java index 11bfa99ab23..306e5f0f3fb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java @@ -42,78 +42,6 @@ public class FailingTemplateTests extends TestCase { */ - /** - * template < class T > struct A { - * void f( int ); - * template < class T2 > void f( T2 ); - * }; - * - * template <> void A::f(int) {} //non-template member - * template <> template<> void A::f<>( int ) {} //template member - * - * int main(){ - * A< char > ac; - * ac.f( 1 ); //non-template - * ac.f( 'c' ); //template - * ac.f<>(1); //template - * } - * @throws Exception - */ - public void test_14_5_2__2_MemberFunctionTemplates() throws Exception{ - - //This code snippet is misleading, the two definitions are actually - //explicit specializations for T = int, and so would not be used - //below or A< char >. This needs to be rewritten. - - -// newTable(); -// -// ITemplateSymbol templateA = table.newTemplateSymbol( "A" ); -// ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); -// templateA.addParameter( T ); -// -// table.getCompilationUnit().addSymbol( templateA ); -// -// IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); -// templateA.addSymbol( A ); -// -// IParameterizedSymbol f1 = table.newParameterizedSymbol("f", TypeInfo.t_function ); -// f1.addParameter( TypeInfo.t_int, 0, null, false ); -// f1.setIsForwardDeclaration( true ); -// A.addSymbol( f1 ); -// -// ITemplateSymbol templateF = table.newTemplateSymbol( "f" ); -// ISymbol T2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); -// -// IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); -// f2.addParameter( T2, null, false ); -// f2.setIsForwardDeclaration( true ); -// templateF.addSymbol( f2 ); -// -// A.addSymbol( templateF ); -// -// List args = new LinkedList(); -// args.add( new TypeInfo( TypeInfo.t_int,0, null ) ); -// ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", new LinkedList(), args ); -// -// LinkedList params = new LinkedList(); -// params.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); -// ISymbol look = factory.lookupMemberFunctionForDefinition( "f", params ); -// assertEquals( look, f1 ); -// -// IParameterizedSymbol f1Def = table.newParameterizedSymbol( "f", TypeInfo.t_function ); -// f1Def.addParameter( TypeInfo.t_int, 0, null, false ); -// look.setTypeSymbol( f1Def ); -// factory.addSymbol( f1Def ); -// -// factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", new LinkedList(), args ); -// assertNotNull( factory ); -// -// args.clear(); -// args.add(table.newSymbol( ParserSymbolTable.EMPTY_NAME, TypeInfo.t_int ) ); -// factory = factory.lookupTemplateForMemberDefinition( "f", new LinkedList(), new LinkedList(), args ); - } - /** * A specialization of a member function template does not override a virtual * function from a base class. diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 1495085848b..b6bb8fc8f5c 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,10 @@ +2004-04-23 Andrew Niefer + - fixed up CompleteParseASTFactory.lookupQualifiedName in the case where the + tokenDuple has 1 segement + - fixed CompleteParseASTFactory.createMethod to handle template ids + - fixed instantiation of member templates + - fixed up handling of explicit specializations + 2004-04-22 John Camelon Fixed https://bugs.eclipse.org/bugs/show_bug.cgi?id=47926 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java index d394e8a673e..286ef9c9c0c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/ITokenDuple.java @@ -56,4 +56,6 @@ public interface ITokenDuple { * @return */ public abstract boolean syntaxOfName(); + + public String extractNameFromTemplateId(); } \ No newline at end of file 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 31f7e58f7a5..a04a2bd68a4 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 @@ -297,8 +297,10 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto else if( name == null ) return null; List [] templateArgLists = name.getTemplateIdArgLists(); + List args = null; int idx = 0; - switch( name.length() ) + String image = null; + switch( name.getSegmentCount() ) { case 0: if( throwOnError ) @@ -306,14 +308,21 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto else return null; case 1: - firstSymbol = name.getFirstToken(); - result = lookupElement(startingScope, firstSymbol.getImage(), type, parameters, lookup ); + image = name.extractNameFromTemplateId(); + args = ( templateArgLists != null ) ? getTemplateArgList( templateArgLists[ 0 ] ) : null; + result = lookupElement(startingScope, image, type, parameters, args, lookup ); + if( result != null ) { if( lookup == LookupType.FORPARENTSCOPE && startingScope instanceof ITemplateFactory ){ - ((ITemplateFactory)startingScope).pushSymbol( result ); + if( args != null ) + ((ITemplateFactory)startingScope).pushTemplateId( result, args ); + else + ((ITemplateFactory)startingScope).pushSymbol( result ); } - addReference( references, createReference( result, firstSymbol.getImage(), firstSymbol.getOffset() )); + addReference( references, createReference( result, image, name.getStartOffset() )); + if( args != null ) + addTemplateIdReferences( references, templateArgLists[0] ); } else { @@ -328,7 +337,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto } } if ( throwOnError ) - handleProblem( IProblem.SEMANTIC_NAME_NOT_FOUND, firstSymbol.getImage(), -1, -1, firstSymbol.getLineNumber() ); + handleProblem( IProblem.SEMANTIC_NAME_NOT_FOUND, image, -1, -1, name.getLineNumber() ); return null; } break; @@ -348,7 +357,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto } if( t.isPointer() ) break; - String image = t.getImage(); + image = t.getImage(); int offset = t.getOffset(); if( templateArgLists != null && templateArgLists[ idx ] != null ){ @@ -361,22 +370,19 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto if( result instanceof IDeferredTemplateInstance ){ result = ((IDeferredTemplateInstance)result).getTemplate().getTemplatedSymbol(); } - + args = ( templateArgLists != null ) ? getTemplateArgList( templateArgLists[ idx ] ) : null; if( t == name.getLastToken() ) - if( templateArgLists != null ) - result = lookupElement((IContainerSymbol)result, image, type, parameters, getTemplateArgList( templateArgLists[idx] ), ( lookup == LookupType.FORDEFINITION ) ? lookup : LookupType.QUALIFIED ); - else - result = lookupElement((IContainerSymbol)result, image, type, parameters, ( lookup == LookupType.FORDEFINITION ) ? lookup : LookupType.QUALIFIED ); + result = lookupElement((IContainerSymbol)result, image, type, parameters, args, ( lookup == LookupType.FORDEFINITION ) ? lookup : LookupType.QUALIFIED ); else if( templateArgLists != null && templateArgLists[idx] != null ) - result = ((IContainerSymbol)result).lookupTemplateId( image, getTemplateArgList( templateArgLists[idx] ) ); + result = ((IContainerSymbol)result).lookupTemplateId( image, args ); else result = ((IContainerSymbol)result).lookupNestedNameSpecifier( image ); if( result != null ){ if( lookup == LookupType.FORPARENTSCOPE && startingScope instanceof ITemplateFactory ){ if( templateArgLists != null && templateArgLists[idx] != null ) - ((ITemplateFactory)startingScope).pushTemplateId( result, getTemplateArgList( templateArgLists[idx] ) ); + ((ITemplateFactory)startingScope).pushTemplateId( result, args ); else ((ITemplateFactory)startingScope).pushSymbol( result ); } @@ -2269,7 +2275,17 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto nameDuple = nameDuple.getLastSegment(); } } - symbol = pst.newParameterizedSymbol( nameDuple.toString(), TypeInfo.t_function ); + String methodName = null; + List templateIdArgList = null; + //template-id? + if( nameDuple.getTemplateIdArgLists() != null ){ + templateIdArgList = nameDuple.getTemplateIdArgLists()[ 0 ]; + methodName = nameDuple.extractNameFromTemplateId(); + } else { + methodName = nameDuple.toString(); + } + + symbol = pst.newParameterizedSymbol( methodName, TypeInfo.t_function ); setFunctionTypeInfoBits(isInline, isFriend, isStatic, symbol); setMethodTypeInfoBits( symbol, isConst, isVolatile, isVirtual, isExplicit ); symbol.setHasVariableArgs( hasVariableArguments ); @@ -2291,9 +2307,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(nameDuple.toString()) ){ + if( parentName.equals(methodName) ){ isConstructor = true; - } else if(nameDuple.getFirstToken().getType() == IToken.tCOMPL && parentName.equals(nameDuple.getLastToken().getImage())){ + } else if(methodName.equals( "~" + parentName )){ //$NON-NLS-1$ isDestructor = true; } } @@ -2318,14 +2334,10 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto List functionReferences = new ArrayList(); - 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 ); - } + functionDeclaration = (IParameterizedSymbol) lookupQualifiedName( ownerScope, nameDuple, + isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, + functionParameters, functionReferences, false, + isFriend ? LookupType.FORFRIENDSHIP : LookupType.FORDEFINITION ); previouslyDeclared = ( functionDeclaration != null ) && functionDeclaration.isType( isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function ); @@ -2361,8 +2373,12 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto ((IDerivableContainerSymbol)ownerScope).addFriend( functionDeclaration ); else ((IDerivableContainerSymbol)ownerScope).addFriend( symbol ); - } else if( !isConstructor ) - ownerScope.addSymbol( symbol ); + } else if( !isConstructor ){ + if( templateIdArgList == null ) + ownerScope.addSymbol( symbol ); + else + ownerScope.addTemplateId( symbol, getTemplateArgList( templateIdArgList ) ); + } else { symbol.setType( TypeInfo.t_constructor ); @@ -2380,6 +2396,9 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto attachSymbolExtension( symbol, method, isFunctionDefinition ); return method; } + + + /** * @param symbol * @param constructorChain 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 d5994762353..0b25435731d 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 @@ -99,14 +99,21 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { if( !template.getExplicitSpecializations().isEmpty() ){ List argList = new LinkedList(); + boolean hasAllParams = true; Iterator templateParams = template.getParameterList().iterator(); while( templateParams.hasNext() ){ - argList.add( argMap.get( templateParams.next() ) ); + Object obj = argMap.get( templateParams.next() ); + if( obj == null ){ + hasAllParams = false; + break; + } + argList.add( obj ); + } + if( hasAllParams){ + ISymbol temp = TemplateEngine.checkForTemplateExplicitSpecialization( template, symbol, argList ); + if( temp != null ) + containedSymbol = temp; } - - ISymbol temp = TemplateEngine.checkForTemplateExplicitSpecialization( template, symbol, argList ); - if( temp != null ) - containedSymbol = temp; } Map instanceMap = argMap; @@ -797,49 +804,6 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { return null; } -// public ITemplateFactory lookupTemplateForMemberDefinition( String name, List parameters, List arguments ) throws ParserSymbolTableException{ -// LookupData data = new LookupData( name, TypeInfo.t_any ); -// -// ParserSymbolTable.lookup( data, this ); -// -// 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; -// } - - public List prefixLookup( TypeFilter filter, String prefix, boolean qualified ) throws ParserSymbolTableException{ LookupData data = new LookupData( prefix, filter ); data.qualified = qualified; 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 05d8e229a6f..47ff4ca3369 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 @@ -42,6 +42,7 @@ public interface ITemplateSymbol extends IParameterizedSymbol { public List findArgumentsFor( IContainerSymbol instance ); public void addInstantiation( IContainerSymbol instance, List args ); + public void removeInstantiation( IContainerSymbol symbol ); public void addExplicitSpecialization( ISymbol symbol, List args ) throws ParserSymbolTableException; @@ -77,8 +78,4 @@ public interface ITemplateSymbol extends IParameterizedSymbol { public static final DeferredKind PARENT = new DeferredKind( 2 ); public static final DeferredKind TYPE_SYMBOL = new DeferredKind( 3 ); } - - - - } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java index 78ab5e94d3c..600432a0ed1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java @@ -80,21 +80,24 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz } } - Iterator iter = getParameterList().iterator(); - - newParameterized.getParameterList().clear(); - newParameterized.getParameterMap().clear(); - - ISymbol param = null, newParam = null; - - while( iter.hasNext() ){ - param = (ISymbol) iter.next(); - newParam = param.instantiate( template, argMap ); + //handle template parameter lists in TemplateSymbol, only do function parameter lists here. + if( !isType( TypeInfo.t_template ) ){ + Iterator iter = getParameterList().iterator(); - newParameterized.getParameterList().add( newParam ); - if( !newParam.getName().equals( ParserSymbolTable.EMPTY_NAME ) ){ - newParameterized.getParameterMap().put( newParam.getName(), newParam ); - } + newParameterized.getParameterList().clear(); + newParameterized.getParameterMap().clear(); + + ISymbol param = null, newParam = null; + + while( iter.hasNext() ){ + param = (ISymbol) iter.next(); + newParam = param.instantiate( template, argMap ); + + newParameterized.getParameterList().add( newParam ); + if( !newParam.getName().equals( ParserSymbolTable.EMPTY_NAME ) ){ + newParameterized.getParameterMap().put( newParam.getName(), newParam ); + } + } } return newParameterized; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java index c68f1ce698c..259ab613636 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java @@ -565,7 +565,7 @@ public class ParserSymbolTable { } if( numTemplateFunctions > 0 ){ - if( data.parameters != null && !data.exactFunctionsOnly ){ + if( data.parameters != null && ( !data.exactFunctionsOnly || data.templateParameters != null ) ){ List fns = TemplateEngine.selectTemplateFunctions( templateFunctionSet, data.parameters, data.templateParameters ); functionSet.addAll( fns ); numFunctions = functionSet.size(); @@ -984,7 +984,7 @@ public class ParserSymbolTable { reduceToViable( data, functions ); - if( data.exactFunctionsOnly ){ + if( data.exactFunctionsOnly && data.templateParameters == null ){ if( functions.size() == 1 ){ return (IParameterizedSymbol) functions.get( 0 ); } else if( functions.size() == 0 ){ @@ -1153,7 +1153,10 @@ public class ParserSymbolTable { if( !hasWorse ){ if( !hasBetter ){ //if they are both template functions, we can order them that way - if( bestFn.isTemplateInstance() && currFn.isTemplateInstance() ){ + boolean bestIsTemplate = bestFn.getContainingSymbol() instanceof ITemplateSymbol; + boolean currIsTemplate = currFn.getContainingSymbol() instanceof ITemplateSymbol; + if( bestIsTemplate && currIsTemplate ) + { ITemplateSymbol t1 = (ITemplateSymbol) bestFn.getInstantiatedSymbol().getContainingSymbol(); ITemplateSymbol t2 = (ITemplateSymbol) currFn.getInstantiatedSymbol().getContainingSymbol(); int order = TemplateEngine.orderTemplateFunctions( t1, t2 ); @@ -1163,13 +1166,13 @@ public class ParserSymbolTable { ambiguous = false; } } - //we prefer normal functions over template functions, unless the specified template arguments - else if( bestFn.isTemplateInstance() && !currFn.isTemplateInstance() ){ + //we prefer normal functions over template functions, unless we specified template arguments + else if( bestIsTemplate && !currIsTemplate ){ if( data.templateParameters == null ) hasBetter = true; else ambiguous = false; - } else if( !bestFn.isTemplateInstance() && currFn.isTemplateInstance() ){ + } else if( !bestIsTemplate && currIsTemplate ){ if( data.templateParameters == null ) ambiguous = false; else 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 06e7a30a121..330f1fdabe4 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 @@ -1297,8 +1297,8 @@ public final class TemplateEngine { return false; } - ITemplateSymbol t1 = (ITemplateSymbol) getContainingTemplate( p1 );//.getContainingSymbol(); - ITemplateSymbol t2 = (ITemplateSymbol) getContainingTemplate( p2 );//.getContainingSymbol(); + ITemplateSymbol t1 = getContainingTemplate( p1 ); + ITemplateSymbol t2 = getContainingTemplate( p2 ); if( p1.getTypeInfo().getTemplateParameterType() == TypeInfo.t_typeName ) { 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 961c497ee01..4b94d120153 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 @@ -57,7 +57,8 @@ public class TemplateFactory extends ExtensibleSymbol implements ITemplateFactor */ public void addTemplateId(ISymbol symbol, List args) throws ParserSymbolTableException { ISymbol previous = findPreviousSymbol( symbol, args ); - ITemplateSymbol origTemplate = (previous != null ) ? (ITemplateSymbol) previous.getContainingSymbol() : null; + ITemplateSymbol origTemplate = (previous != null && previous.getContainingSymbol() instanceof ITemplateSymbol ) + ? (ITemplateSymbol) previous.getContainingSymbol() : null; if( origTemplate == null ){ throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); @@ -131,7 +132,6 @@ public class TemplateFactory extends ExtensibleSymbol implements ITemplateFactor int numSymbols = symbols.size(); if( templateParamState ){ - ITemplateSymbol template = (ITemplateSymbol) container.getContainingSymbol(); List args = (List) argMap.get( container ); addExplicitSpecialization( (ITemplateSymbol) container.getContainingSymbol(), symbol, args ); return; @@ -311,6 +311,19 @@ public class TemplateFactory extends ExtensibleSymbol implements ITemplateFactor private void addExplicitSpecialization( ITemplateSymbol template, ISymbol symbol, List arguments ) throws ParserSymbolTableException { template.addExplicitSpecialization( symbol, arguments ); + Iterator i = symbols.iterator(); + while( i.hasNext() ){ + IContainerSymbol sym = (IContainerSymbol) i.next(); + ISymbol instantiated = sym.getInstantiatedSymbol(); + if( instantiated != null ){ + IContainerSymbol container = instantiated.getContainingSymbol(); + if( container.isType( TypeInfo.t_template ) ){ + ((ITemplateSymbol) container ).removeInstantiation( sym ); + } + } + + } + if( getASTExtension() != null ){ ASTTemplateSpecialization spec = (ASTTemplateSpecialization) getASTExtension().getPrimaryDeclaration(); spec.setOwnedDeclaration( symbol ); @@ -527,7 +540,7 @@ public class TemplateFactory extends ExtensibleSymbol implements ITemplateFactor if( look instanceof ITemplateSymbol ){ ITemplateSymbol t = TemplateEngine.selectTemplateOrSpecialization( (ITemplateSymbol) look, getNextAvailableTemplate().getParameterList(), arguments ); - look = ((ITemplateSymbol) look).getTemplatedSymbol(); + look = t.getTemplatedSymbol(); } return (IContainerSymbol) (( look instanceof IContainerSymbol) ? look : null); } 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 728b309d4b5..4272416073b 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 @@ -162,6 +162,26 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb } } + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( !isTemplateMember() ){ + return null; + } + + TemplateSymbol newTemplate = (TemplateSymbol) super.instantiate( template, argMap ); + + //we don't want to instantiate the template parameters, just the defaults if there are any + Iterator iter = newTemplate.getParameterList().iterator(); + ISymbol param = null; + while( iter.hasNext() ){ + param = (ISymbol) iter.next(); + Object obj = param.getTypeInfo().getDefault(); + if( obj instanceof TypeInfo ){ + param.getTypeInfo().setDefault( TemplateEngine.instantiateTypeInfo( (TypeInfo) obj, template, argMap ) ); + } + } + + return newTemplate; + } public void addParameter( ISymbol param ) { throw new ParserSymbolTableError( ParserSymbolTableError.r_OperationNotSupported ); @@ -278,11 +298,24 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb if( found == null && getTemplatedSymbol().getName().equals( symbol.getName() ) ){ found = getTemplatedSymbol(); - IContainerSymbol instance = findInstantiation( args ); + IContainerSymbol instance = findInstantiation( actualArgs ); if( instance != null ){ _instantiations.remove( findArgumentsFor( instance ) ); } } + + if( found != null && found.getTypeInfo().isForwardDeclaration() && found.getTypeSymbol() == symbol ){ + //in defining the explicit specialization for a member function, the factory would have set + //the specialization as the definition of the original declaration, which it is not + found.setTypeSymbol( null ); + } + + //TODO, once we can instantiate members as we need them instead of at the same time as the class + //then found should stay as the instance, for now though, we need the original (not 100% correct + //but the best we can do for now) + while( found.isTemplateInstance() ){ + found = found.getInstantiatedSymbol(); + } if( found != null ){ symbol.setIsTemplateMember( true ); @@ -357,6 +390,13 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb return null; } + public void removeInstantiation( IContainerSymbol symbol ){ + List args = findArgumentsFor( symbol ); + if( args != null ){ + _instantiations.remove( args ); + } + } + public Map getDefinitionParameterMap(){ if( _defnParameterMap == null ){ _defnParameterMap = new HashMap(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java index da930293290..4a83268c3c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java @@ -229,6 +229,7 @@ public class TypeInfo { "enum", //$NON-NLS-1$ t_enumeration "", //$NON-NLS-1$ t_constructor "", //$NON-NLS-1$ t_function + "_Bool", //$NON-NLS-1$ t__Bool "bool", //$NON-NLS-1$ t_bool "char", //$NON-NLS-1$ t_char "wchar_t", //$NON-NLS-1$ t_wchar_t @@ -240,7 +241,9 @@ public class TypeInfo { "", //$NON-NLS-1$ t_block "template", //$NON-NLS-1$ t_template "", //$NON-NLS-1$ t_asm - "" //$NON-NLS-1$ t_linkage + "", //$NON-NLS-1$ t_linkage + "", //$NON-NLS-1$ t_templateParameter + "typename" //$NON-NLS-1$ t_typeName }; //Partial ordering : // none < const diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenDuple.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenDuple.java index 31c7dbe4382..a2c491ea7da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenDuple.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/token/TokenDuple.java @@ -437,4 +437,59 @@ public class TokenDuple implements ITokenDuple { return true; return false; } + + public String extractNameFromTemplateId(){ + ITokenDuple nameDuple = getLastSegment(); + + Iterator i = nameDuple.iterator(); + + if( !i.hasNext() ) + return "";//$NON-NLS-1$ + + StringBuffer nameBuffer = new StringBuffer(); + IToken token = (IToken) i.next(); + nameBuffer.append( token.getImage() ); + + if( !i.hasNext() ) + return nameBuffer.toString(); + + //appending of spaces needs to be the same as in toString() + + //destructors + if( token.getType() == IToken.tCOMPL ){ + token = (IToken) i.next(); + nameBuffer.append( token.getImage() ); + } + //operators + else if( token.getType() == IToken.t_operator ){ + token = (IToken) i.next(); + nameBuffer.append( ' ' ); + nameBuffer.append( token.getImage() ); + + if( !i.hasNext() ) + return nameBuffer.toString(); + + //operator new [] and operator delete [] + if( (token.getType() == IToken.t_new || token.getType() == IToken.t_delete) && + (token.getNext().getType() == IToken.tLBRACKET ) ) + { + nameBuffer.append( ' ' ); + nameBuffer.append( ((IToken)i.next()).getImage() ); + nameBuffer.append( ((IToken)i.next()).getImage() ); + } + //operator [] + else if( token.getType() == IToken.tLBRACKET ) + { + nameBuffer.append( ((IToken)i.next()).getImage() ); + } + //operator ( ) + else if( token.getType() == IToken.tLBRACE ) + { + nameBuffer.append( ' ' ); + nameBuffer.append( ((IToken)i.next()).getImage() ); + } + } + + return nameBuffer.toString(); + } }