diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index f65d0999da1..3a55a89905a 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,9 @@ +2003-03-23 Andrew Niefer + bug 55673 & fix recursive loop in template instantiation + -parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.testInstantiatingDeferredInstances() + -parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.testTemplateArgumentDeduction() + -parser/org/eclipse/cdt/core/parser/tests/CompleteParseASTTest.testBug55673() + 2003-03-22 John Camelon Added CompleteParseASTTest::testBug54531(). 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 ecaa1da316b..55bb540f03c 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 @@ -1771,6 +1771,59 @@ public class CompleteParseASTTest extends CompleteParseBaseTest new Task( f21, 1, false, false ) ) ); } + public void testInstantiatingDeferredInstances() throws Exception{ + Writer writer = new StringWriter(); + writer.write( "template < class T > struct A { A < T > next; }; \n" ); + writer.write( "A< int > a; \n" ); + + Iterator i = parse( writer.toString() ).getDeclarations(); + } + + public void testTemplateArgumentDeduction() throws Exception{ + Writer writer = new StringWriter(); + writer.write( "template< class T > struct B {}; \n" ); + writer.write( "template< class T > struct D : public B < T > {}; \n" ); + writer.write( "struct D2 : public B< int > {}; \n" ); + writer.write( "template< class T > T f( B & ) {} \n" ); + writer.write( "void test( int ); \n" ); + writer.write( "void test( char ); \n" ); + writer.write( "void main() { \n" ); + writer.write( " D d; \n" ); + writer.write( " D2 d2; \n" ); + writer.write( " test( f( d ) ); \n" ); + writer.write( " test( f( d2 ) ); \n" ); + writer.write( "} \n" ); + + Iterator i = parse( writer.toString() ).getDeclarations(); + + IASTTemplateDeclaration templateB = (IASTTemplateDeclaration) i.next(); + IASTTemplateDeclaration templateD = (IASTTemplateDeclaration) i.next(); + IASTClassSpecifier D2 = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); + IASTTemplateDeclaration templateF = (IASTTemplateDeclaration) i.next(); + IASTFunction test1 = (IASTFunction) i.next(); + IASTFunction test2 = (IASTFunction) i.next(); + IASTFunction main = (IASTFunction) i.next(); + + assertFalse( i.hasNext() ); + assertReferenceTask( new Task( test1, 2, false, false ) ); + } + public void testBug55673() throws Exception{ + Writer writer = new StringWriter(); + writer.write( "struct Example { int i; int ( * pfi ) ( int ); }; "); + + Iterator iter = parse( writer.toString() ).getDeclarations(); + + IASTClassSpecifier example = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)iter.next()).getTypeSpecifier(); + assertFalse( iter.hasNext() ); + + iter = getDeclarations( example ); + + IASTField i = (IASTField) iter.next(); + IASTField pfi = (IASTField) iter.next(); + + assertFalse( iter.hasNext() ); + } + public void testBug54531() throws Exception { Iterator i = parse( "typedef enum _A {} A, *pA;" ).getDeclarations(); diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 5ccc3d59c08..e02e5236154 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,3 +1,8 @@ +2004-03-23 Andrew Niefer + -fix recursive loop leading to StackOverFlowException during template instantiation + -fix copy constructors for templated classes + -fix bug 55673 + 2004-03-22 Andrew Niefer -handling of Typedefs -handle unbalanced preprocessor condition in scanner 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 9f82e491046..6f599e7b9df 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 @@ -367,10 +367,11 @@ public class DeclarationWrapper implements IDeclaratorOwner Declarator d = declarator.getOwnedDeclarator(); Iterator i = d.getPointerOperators().iterator(); + boolean isWithinClass = scope instanceof IASTClassSpecifier; + boolean isFunction = (declarator.getParameters().size() != 0); if( !i.hasNext() ) { - boolean isWithinClass = scope instanceof IASTClassSpecifier; - boolean isFunction = (declarator.getParameters().size() != 0); + if (isTypedef()) return createTypedef(declarator, true); @@ -408,8 +409,12 @@ public class DeclarationWrapper implements IDeclaratorOwner getStartingOffset(), getStartingLine(), d .getNameStartOffset(), d.getNameEndOffset(), d .getNameLine()); - else - return astFactory.createVariable( scope, name, auto, d.getInitializerClause(), d.getBitFieldExpression(), abs, mutable, extern, register, staticc, getStartingOffset(), getStartingLine(), d.getNameStartOffset(), d.getNameEndOffset(), d.getNameLine(), d.getConstructorExpression() ); + else { + if( isWithinClass ) + return astFactory.createField( scope, name, auto, d.getInitializerClause(), d.getBitFieldExpression(), abs, mutable, extern, register, staticc, getStartingOffset(), getStartingLine(), d.getNameStartOffset(), d.getNameEndOffset(), d.getNameLine(), d.getConstructorExpression(), ((IASTClassSpecifier)scope).getCurrentVisibilityMode() ); + else + return astFactory.createVariable( scope, name, auto, d.getInitializerClause(), d.getBitFieldExpression(), abs, mutable, extern, register, staticc, getStartingOffset(), getStartingLine(), d.getNameStartOffset(), d.getNameEndOffset(), d.getNameLine(), d.getConstructorExpression() ); + } } else 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 5bdc1db408c..ca7ba7eb479 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 @@ -70,7 +70,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva newWrapper = new ParentWrapper( wrapper.getParent(), wrapper.isVirtual(), wrapper.getAccess(), wrapper.getOffset(), wrapper.getReferences() ); ISymbol parent = newWrapper.getParent(); if( parent instanceof IDeferredTemplateInstance ){ - newWrapper.setParent( ((IDeferredTemplateInstance)parent).instantiate( template, argMap ) ); + template.registerDeferredInstatiation( newSymbol, newWrapper, ITemplateSymbol.DeferredKind.PARENT, argMap ); } else if( parent.isType( TypeInfo.t_templateParameter ) && argMap.containsKey( parent ) ){ TypeInfo info = (TypeInfo) argMap.get( parent ); newWrapper.setParent( info.getTypeSymbol() ); @@ -79,19 +79,22 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva newSymbol.getParents().add( newWrapper ); } -// Iterator constructors = getConstructors().iterator(); -// newSymbol.getConstructors().clear(); -// IParameterizedSymbol constructor = null; -// while( constructors.hasNext() ){ -// constructor = (IParameterizedSymbol) constructors.next(); -// newSymbol.getConstructors().add( constructor.instantiate( template, argMap ) ); -// } - //TODO: friends return newSymbol; } + public void instantiateDeferredParent( ParentWrapper wrapper, ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + Iterator parents = getParents().iterator(); + ParentWrapper w = null; + while( parents.hasNext() ) { + w = (ParentWrapper) parents.next(); + if( w == wrapper ){ + wrapper.setParent( wrapper.getParent().instantiate( template, argMap ) ); + } + } + } + public void addSymbol(ISymbol symbol) throws ParserSymbolTableException { super.addSymbol( symbol ); @@ -172,7 +175,12 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva public void addCopyConstructor() throws ParserSymbolTableException{ List parameters = new LinkedList(); - TypeInfo param = new TypeInfo( TypeInfo.t_type, TypeInfo.isConst, this, new TypeInfo.PtrOp( TypeInfo.PtrOp.t_reference, false, false ), false ); + ISymbol paramType = this; + if( getContainingSymbol() instanceof ITemplateSymbol ){ + paramType = TemplateEngine.instantiateWithinTemplateScope( this, (ITemplateSymbol) getContainingSymbol() ); + } + + TypeInfo param = new TypeInfo( TypeInfo.t_type, TypeInfo.isConst, paramType, new TypeInfo.PtrOp( TypeInfo.PtrOp.t_reference, false, false ), false ); parameters.add( param ); IParameterizedSymbol constructor = 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 07262f394ef..05d8e229a6f 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 @@ -59,4 +59,26 @@ public interface ITemplateSymbol extends IParameterizedSymbol { public IDeferredTemplateInstance deferredInstance( List args ); public Map getExplicitSpecializations(); + + /** + * @param symbol + * @param type + * @param kind + */ + public void registerDeferredInstatiation( Object obj0, Object obj1, DeferredKind kind, Map argMap ); + + public static class DeferredKind{ + private DeferredKind( int v ){ + _val = v; + } + private int _val; + + public static final DeferredKind RETURN_TYPE = new DeferredKind( 1 ); + 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 06d52a5d2dd..0837ec90f07 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 @@ -73,7 +73,10 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz newParameterized.getReturnType().setInstantiatedSymbol( _returnType ); } } else { - newParameterized.setReturnType( _returnType.instantiate( template, argMap ) ); + if( _returnType instanceof IDeferredTemplateInstance ) + template.registerDeferredInstatiation( newParameterized, _returnType, ITemplateSymbol.DeferredKind.RETURN_TYPE, argMap ); + else + newParameterized.setReturnType( _returnType.instantiate( template, argMap ) ); } } @@ -97,6 +100,10 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz return newParameterized; } + public void instantiateDeferredReturnType( ISymbol returnType, ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + setReturnType( returnType.instantiate( template, argMap ) ); + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addParameter(org.eclipse.cdt.internal.core.parser.pst.ISymbol) */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java index d87afc76858..d9c64557421 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java @@ -113,6 +113,8 @@ public class SpecializedSymbol extends TemplateSymbol implements ISpecializedSym instance = (IContainerSymbol) symbol.instantiate( this, argMap ); addInstantiation( instance, actualArgs ); + processDeferredInstantiations(); + return instance; } } 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 c5ee8a16c42..1f64c22ab35 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 @@ -33,9 +33,10 @@ public final class TemplateEngine { } else { if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol() instanceof IDeferredTemplateInstance ){ IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) info.getTypeSymbol(); - TypeInfo newInfo = new TypeInfo( info ); - newInfo.setTypeSymbol( deferred.instantiate( template, argMap ) ); + //newInfo.setTypeSymbol( deferred.instantiate( template, argMap ) ); + template.registerDeferredInstatiation( newInfo, deferred, ITemplateSymbol.DeferredKind.TYPE_SYMBOL, argMap ); + newInfo.setTypeSymbol( deferred ); return newInfo; } else if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol().isType( TypeInfo.t_templateParameter ) && @@ -65,6 +66,10 @@ public final class TemplateEngine { } } + static protected void instantiateDeferredTypeInfo( TypeInfo info, ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException { + info.setTypeSymbol( info.getTypeSymbol().instantiate( template, argMap ) ); + } + static protected ITemplateSymbol matchTemplatePartialSpecialization( ITemplateSymbol template, List args ) throws ParserSymbolTableException{ if( template == null ){ return null; @@ -736,6 +741,7 @@ public final class TemplateEngine { IParameterizedSymbol function = (IParameterizedSymbol)templatedSymbol; function = (IParameterizedSymbol) function.instantiate( spec1, map ); + ((TemplateSymbol)spec1).processDeferredInstantiations(); Map m1 = deduceTemplateArgumentsUsingParameterList( spec2, function); @@ -747,6 +753,7 @@ public final class TemplateEngine { function = (IParameterizedSymbol)templatedSymbol; function = (IParameterizedSymbol) function.instantiate( spec2, map ); + ((TemplateSymbol)spec2).processDeferredInstantiations(); Map m2 = deduceTemplateArgumentsUsingParameterList( spec1, function ); 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 c2bd5dd2a1c..205330eb9b7 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 @@ -16,6 +16,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.eclipse.cdt.internal.core.parser.pst.DerivableContainerSymbol.ParentWrapper; import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp; /** @@ -150,6 +151,9 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb instance = (IContainerSymbol) symbol.instantiate( template, map ); addInstantiation( instance, actualArgs ); + + processDeferredInstantiations(); + return instance; } } @@ -361,10 +365,45 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb } return _explicitSpecializations; } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateSymbol#registerDeferredInstatiation(org.eclipse.cdt.internal.core.parser.pst.ParameterizedSymbol, org.eclipse.cdt.internal.core.parser.pst.ISymbol, org.eclipse.cdt.internal.core.parser.pst.ITemplateSymbol.DeferredKind) + */ + public void registerDeferredInstatiation( Object obj0, Object obj1, DeferredKind kind, Map argMap ) { + if( _deferredInstantiations == null ) + _deferredInstantiations = new LinkedList(); + + _deferredInstantiations.add( new Object [] { obj0, obj1, kind, argMap } ); + } + + + protected void processDeferredInstantiations() throws ParserSymbolTableException{ + if( _deferredInstantiations == null ) + return; + + Iterator iter = _deferredInstantiations.iterator(); + while( iter.hasNext() ){ + Object [] objs = (Object [])iter.next(); + + DeferredKind kind = (DeferredKind) objs[2]; + + if( kind == DeferredKind.PARENT ){ + DerivableContainerSymbol d = (DerivableContainerSymbol) objs[0]; + d.instantiateDeferredParent( (ParentWrapper) objs[ 1 ], this, (Map) objs[3] ); + } else if( kind == DeferredKind.RETURN_TYPE ){ + ParameterizedSymbol p = (ParameterizedSymbol) objs[0]; + p.instantiateDeferredReturnType( (ISymbol) objs[1], this, (Map) objs[3] ); + } else if( kind == DeferredKind.TYPE_SYMBOL ){ + TemplateEngine.instantiateDeferredTypeInfo( (TypeInfo) objs[0], this, (Map) objs[3] ); + } + } + } 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; + private HashMap _instantiations; + private LinkedList _deferredInstantiations; //used to avoid recursive loop + } \ No newline at end of file