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 36af31ebd0d..43959774cb5 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 @@ -33,7 +33,6 @@ import org.eclipse.cdt.core.parser.ast.IASTTemplateSpecialization; import org.eclipse.cdt.core.parser.ast.IASTTypedefDeclaration; import org.eclipse.cdt.core.parser.ast.IASTVariable; import org.eclipse.cdt.internal.core.parser.ParserException; -import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableError; /** * @author aniefer @@ -974,7 +973,15 @@ public class CompleteParseASTTemplateTest extends CompleteParseBaseTest { try{ parse( "template < class T > class A : public A< T * > {}; A a;" ).getDeclarations(); //NON-NLS-1$ assertTrue( false ); - } catch ( ParserSymbolTableError e ){ + } catch ( ParserException e ){ + assertTrue( e.getMessage().equals( "FAILURE" ) ); //$NON-NLS-1$ + } + + try{ + parse( "template < class T > class A { A f(); }; A< int > a;" ).getDeclarations(); //NON-NLS-1$ + assertTrue( false ); + } catch ( ParserException e ){ + assertTrue( e.getMessage().equals( "FAILURE" ) ); //$NON-NLS-1$ } } } 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 76a0651e77a..3155b0d10d3 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 @@ -97,6 +97,27 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva } } + /** + * @param symbol + * @param symbol2 + * @param map + */ + public void discardDeferredParent(IDeferredTemplateInstance parent, ITemplateSymbol template, Map map) { + List parents = getParents(); + int size = parents.size(); + ParentWrapper w = null; + ISymbol originalParent = parent.getTemplate().getTemplatedSymbol(); + for( int i = 0; i < size; i++ ){ + w = (ParentWrapper) parents.get(i); + ISymbol instance = w.getParent(); + if( instance.getInstantiatedSymbol() == originalParent ){ + parents.remove( i ); + template.removeInstantiation( (IContainerSymbol) instance ); + break; + } + } + } + protected void collectInstantiatedConstructor( IParameterizedSymbol constructor ){ if( constructor.isType( TypeInfo.t_constructor ) ) addToConstructors( constructor ); 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 8b0ea64e369..54999f21f86 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 @@ -105,6 +105,16 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz setReturnType( returnType.instantiate( template, argMap ) ); } + /** + * @param symbol + * @param symbol2 + * @param map + */ + public void discardDeferredReturnType(ISymbol oldReturnType, TemplateSymbol template, Map map) { + ISymbol returnType = getReturnType(); + setReturnType( null ); + template.removeInstantiation( (IContainerSymbol) returnType ); + } public void prepareForParameters( int numParams ){ if( _parameterList == Collections.EMPTY_LIST ){ 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 7f181e46010..552aca66742 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 @@ -111,8 +111,15 @@ public class SpecializedSymbol extends TemplateSymbol implements ISpecializedSym instance = (IContainerSymbol) symbol.instantiate( this, argMap ); addInstantiation( instance, actualArgs ); - processDeferredInstantiations(); - + try{ + processDeferredInstantiations(); + } catch( ParserSymbolTableException e ){ + if( e.reason == ParserSymbolTableException.r_RecursiveTemplate ){ + //clean up some. + removeInstantiation( instance ); + } + throw e; + } 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 d2875848299..4b14414bcc0 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 @@ -69,6 +69,18 @@ public final class TemplateEngine { info.setTypeSymbol( info.getTypeSymbol().instantiate( template, argMap ) ); } + /** + * @param info + * @param symbol + * @param map + */ + public static void discardDeferredTypeInfo(TypeInfo info, TemplateSymbol template, Map map) { + ISymbol instance = info.getTypeSymbol(); + if( !(instance instanceof IDeferredTemplateInstance ) ) + template.removeInstantiation( (IContainerSymbol) instance ); + info.setTypeSymbol( null ); + } + static protected ITemplateSymbol matchTemplatePartialSpecialization( ITemplateSymbol template, List args ) throws ParserSymbolTableException{ if( template == null ){ return 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 1048dcd96bf..bd45b640489 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 @@ -150,7 +150,15 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb instance = (IContainerSymbol) symbol.instantiate( template, map ); addInstantiation( instance, actualArgs ); - processDeferredInstantiations(); + try{ + processDeferredInstantiations(); + } catch( ParserSymbolTableException e ){ + if( e.reason == ParserSymbolTableException.r_RecursiveTemplate ){ + //clean up some. + removeInstantiation( instance ); + } + throw e; + } return instance; } @@ -434,10 +442,11 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb } _processingDeferred = true; int numDeferred = _deferredInstantiations.size(); + int numProcessed = 0; int loopCount = 0; - while( numDeferred > 0 ){ - while( numDeferred > 0 ) { - Object [] objs = (Object [])_deferredInstantiations.get(0); + while( numDeferred > numProcessed ){ + for( int i = numProcessed; i < numDeferred; i++ ){ + Object [] objs = (Object [])_deferredInstantiations.get(i); DeferredKind kind = (DeferredKind) objs[2]; @@ -450,17 +459,38 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb } else if( kind == DeferredKind.TYPE_SYMBOL ){ TemplateEngine.instantiateDeferredTypeInfo( (TypeInfo) objs[0], this, (Map) objs[3] ); } - - _deferredInstantiations.remove( 0 ); - numDeferred--; + numProcessed++; } numDeferred = _deferredInstantiations.size(); - if( ++loopCount > ParserSymbolTable.TEMPLATE_LOOP_THRESHOLD ) + if( ++loopCount > ParserSymbolTable.TEMPLATE_LOOP_THRESHOLD ){ + discardDeferredInstantiations(); + _processingDeferred = false; throw new ParserSymbolTableException( ParserSymbolTableException.r_RecursiveTemplate ); + } } _processingDeferred = false; } + private void discardDeferredInstantiations(){ + int size = _deferredInstantiations.size(); + for( int i = 0; i < size; i++ ){ + Object [] objs = (Object []) _deferredInstantiations.get(i); + + DeferredKind kind = (DeferredKind) objs[2]; + + if( kind == DeferredKind.PARENT ){ + DerivableContainerSymbol d = (DerivableContainerSymbol) objs[0]; + d.discardDeferredParent( (IDeferredTemplateInstance) objs[1], this, (Map) objs[3] ); + } else if( kind == DeferredKind.RETURN_TYPE ){ + ParameterizedSymbol p = (ParameterizedSymbol) objs[0]; + p.discardDeferredReturnType( (ISymbol) objs[1], this, (Map) objs[3] ); + } else if( kind == DeferredKind.TYPE_SYMBOL ){ + TemplateEngine.discardDeferredTypeInfo( (TypeInfo) objs[0], this, (Map) objs[3] ); + } + } + _deferredInstantiations.clear(); + } + private List _specializations = Collections.EMPTY_LIST; //template specializations private Map _explicitSpecializations = Collections.EMPTY_MAP; //explicit specializations private Map _defnParameterMap = Collections.EMPTY_MAP; //members could be defined with different template parameter names