From b6aed83db291f750864986ec65a53664b71fc2a2 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Thu, 3 Jun 2004 18:48:17 +0000 Subject: [PATCH] fix bug 64939 - recursive loop --- .../tests/CompleteParseASTTemplateTest.java | 10 ++++ .../org/eclipse/cdt/core/parser/IProblem.java | 2 + .../core/parser/ParserMessages.properties | 1 + .../internal/core/parser/problem/Problem.java | 3 ++ .../core/parser/pst/ITemplateSymbol.java | 1 + .../core/parser/pst/ParserSymbolTable.java | 1 + .../pst/ParserSymbolTableException.java | 4 ++ .../core/parser/pst/TemplateSymbol.java | 48 +++++++++++++------ 8 files changed, 55 insertions(+), 15 deletions(-) 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 2fe1c79c61b..36af31ebd0d 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,6 +33,7 @@ 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 @@ -967,4 +968,13 @@ public class CompleteParseASTTemplateTest extends CompleteParseBaseTest { parent = (IASTBaseSpecifier) A3.getBaseClauses().next(); assertEquals( parent.getParentClassSpecifier(), A2 ); } + + public void testBug64939() throws Exception + { + try{ + parse( "template < class T > class A : public A< T * > {}; A a;" ).getDeclarations(); //NON-NLS-1$ + assertTrue( false ); + } catch ( ParserSymbolTableError e ){ + } + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java index 7d7381dc454..6cc95075f76 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/IProblem.java @@ -429,4 +429,6 @@ public interface IProblem public static final int SEMANTIC_MALFORMED_EXPRESSION = SEMANTICS_RELATED | 0x010; public static final int SEMANTIC_ILLFORMED_FRIEND = SEMANTICS_RELATED | 0x011; + + public static final int SEMANTIC_RECURSIVE_TEMPLATE_INSTANTIATION = SEMANTICS_RELATED | 0x012; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties index 86881b870c4..2a8dfb73fd2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserMessages.properties @@ -63,3 +63,4 @@ ASTProblemFactory.error.semantic.pst.unableToResolveFunction=Unable to resolve f ASTProblemFactory.error.semantic.pst.invalidTemplateArgument=Invalid template argument: {0} ASTProblemFactory.error.semantic.pst.invalidTemplateParameter=Invalid template parameter: {0} ASTProblemFactory.error.semantic.pst.redeclaredTemplateParameter=Redeclaration of template parameter: {0} +ASTProblemFactory.error.semantic.pst.recursiveTemplateInstantiation=Possible infinite recursive loop encountered while instantiating {0} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/Problem.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/Problem.java index 559e5006aa6..bb94724fb56 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/Problem.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/problem/Problem.java @@ -145,6 +145,9 @@ public class Problem implements IProblem { errorMessages.put( new Integer( IProblem.SEMANTIC_REDECLARED_TEMPLATE_PARAMETER ), ParserMessages.getString("ASTProblemFactory.error.semantic.pst.redeclaredTemplateParameter")); //$NON-NLS-1$ + errorMessages.put( + new Integer( IProblem.SEMANTIC_RECURSIVE_TEMPLATE_INSTANTIATION ), + ParserMessages.getString("ASTProblemFactory.error.semantic.pst.recursiveTemplateInstantiation")); //$NON-NLS-1$ errorMessages.put( new Integer(IProblem.PREPROCESSOR_POUND_ERROR), ParserMessages.getString("ScannerProblemFactory.error.preproc.error")); //$NON-NLS-1$ 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 48973a1a7b5..03641dcb685 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 @@ -67,6 +67,7 @@ public interface ITemplateSymbol extends IParameterizedSymbol { * @param kind */ public void registerDeferredInstatiation( Object obj0, Object obj1, DeferredKind kind, Map argMap ); + public int getNumberDeferredInstantiations(); public static class DeferredKind{ private DeferredKind( int v ){ 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 994805268f9..5319ccc0607 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 @@ -40,6 +40,7 @@ import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp; public class ParserSymbolTable { public static final int TYPE_LOOP_THRESHOLD = 50; + public static final int TEMPLATE_LOOP_THRESHOLD = 10; public static final String EMPTY_NAME = ""; //$NON-NLS-1$ public static final String THIS = "this"; //$NON-NLS-1$ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java index ec3030988b9..b1c058861d4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java @@ -45,7 +45,9 @@ public class ParserSymbolTableException extends Exception { public static final int r_BadTemplateArgument = 8; public static final int r_BadTemplateParameter = 9; public static final int r_RedeclaredTemplateParam = 10; + public static final int r_RecursiveTemplate = 11; public int reason = -1; + /** * @return */ @@ -74,6 +76,8 @@ public class ParserSymbolTableException extends Exception { return IProblem.SEMANTIC_INVALID_TEMPLATE_PARAMETER; case r_RedeclaredTemplateParam: return IProblem.SEMANTIC_REDECLARED_TEMPLATE_PARAMETER; + case r_RecursiveTemplate: + return IProblem.SEMANTIC_RECURSIVE_TEMPLATE_INSTANTIATION; default: // assert false : this; return -1; 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 06d06e5af58..1048dcd96bf 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 @@ -421,27 +421,44 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb _deferredInstantiations.add( new Object [] { obj0, obj1, kind, argMap } ); } + public int getNumberDeferredInstantiations(){ + return _deferredInstantiations.size(); + } protected void processDeferredInstantiations() throws ParserSymbolTableException{ if( _deferredInstantiations == Collections.EMPTY_LIST ) return; - 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.instantiateDeferredParent( (ISymbol) 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] ); - } + if( _processingDeferred ){ + return; } + _processingDeferred = true; + int numDeferred = _deferredInstantiations.size(); + int loopCount = 0; + while( numDeferred > 0 ){ + while( numDeferred > 0 ) { + Object [] objs = (Object [])_deferredInstantiations.get(0); + + DeferredKind kind = (DeferredKind) objs[2]; + + if( kind == DeferredKind.PARENT ){ + DerivableContainerSymbol d = (DerivableContainerSymbol) objs[0]; + d.instantiateDeferredParent( (ISymbol) 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] ); + } + + _deferredInstantiations.remove( 0 ); + numDeferred--; + } + numDeferred = _deferredInstantiations.size(); + if( ++loopCount > ParserSymbolTable.TEMPLATE_LOOP_THRESHOLD ) + throw new ParserSymbolTableException( ParserSymbolTableException.r_RecursiveTemplate ); + } + _processingDeferred = false; } private List _specializations = Collections.EMPTY_LIST; //template specializations @@ -449,6 +466,7 @@ public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymb private Map _defnParameterMap = Collections.EMPTY_MAP; //members could be defined with different template parameter names private Map _instantiations = Collections.EMPTY_MAP; private List _deferredInstantiations = Collections.EMPTY_LIST; //used to avoid recursive loop + private boolean _processingDeferred = false; } \ No newline at end of file