From 58a835d44128f0b99310aa104a93b22cc73bd908 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Thu, 16 Nov 2006 21:35:51 +0000 Subject: [PATCH] Bug 162230 - Fix a stack overflow that was happening with function template specializations. --- .../parser/tests/ast2/AST2TemplateTests.java | 44 +++++++++++++++++++ .../dom/parser/cpp/CPPClassInstanceScope.java | 2 +- .../core/dom/parser/cpp/CPPClassScope.java | 27 +++++++++--- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 6114abc7f99..3839c63e6fb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -44,6 +44,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; @@ -1942,4 +1943,47 @@ public class AST2TemplateTests extends AST2BaseTest { ICPPVariable c = (ICPPVariable) col.getName(13).resolveBinding(); assertSame( c, col.getName(4).resolveBinding() ); } + + public void testBug162230() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template< class T > class C { \n"); //$NON-NLS-1$ + buffer.append(" public: void * blah; \n"); //$NON-NLS-1$ + buffer.append(" template C(G* g) : blah(g) {} \n"); //$NON-NLS-1$ + buffer.append(" template <> C(char * c) : blah(c) {} \n"); //$NON-NLS-1$ + buffer.append(" template <> C(wchar_t * c) : blah(c) {} \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP, true, true ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding(); + ICPPClassTemplate C = (ICPPClassTemplate) col.getName(1).resolveBinding(); + ICPPField blah = (ICPPField) col.getName(2).resolveBinding(); + ICPPTemplateTypeParameter G = (ICPPTemplateTypeParameter) col.getName(3).resolveBinding(); + ICPPFunctionTemplate ctor = (ICPPFunctionTemplate) col.getName(4).resolveBinding(); + + assertSame(G, col.getName(5).resolveBinding()); + ICPPParameter g = (ICPPParameter) col.getName(6).resolveBinding(); + assertSame(blah, col.getName(7).resolveBinding()); + assertSame(g, col.getName(8).resolveBinding()); + + ICPPSpecialization spec = (ICPPSpecialization) col.getName(9).resolveBinding(); + assertSame(spec.getSpecializedBinding(), ctor); + + ICPPSpecialization c = (ICPPSpecialization) col.getName(10).resolveBinding(); + assertSame(c.getSpecializedBinding(), g); + + assertSame(blah, col.getName(11).resolveBinding()); + assertSame(c, col.getName(12).resolveBinding()); + + ICPPSpecialization spec2 = (ICPPSpecialization) col.getName(13).resolveBinding(); + assertSame(spec.getSpecializedBinding(), ctor); + + ICPPSpecialization c2 = (ICPPSpecialization) col.getName(14).resolveBinding(); + assertSame(c2.getSpecializedBinding(), g); + + assertSame(blah, col.getName(15).resolveBinding()); + assertSame(c2, col.getName(16).resolveBinding()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java index 70d5da7e411..7f1da590c53 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstanceScope.java @@ -96,7 +96,7 @@ public class CPPClassInstanceScope implements ICPPClassScope, IASTInternalScope if( instanceMap.containsKey( n ) ){ binding = (IBinding) instanceMap.get( n ); } else { - binding = forceResolve ? n.resolveBinding() : n.getBinding(); + binding = CPPClassScope.shouldResolve(forceResolve, n, name) ? n.resolveBinding() : n.getBinding(); if (binding instanceof ICPPClassTemplatePartialSpecialization ){ binding = null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java index c6c10743fe6..68964cff4a7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java @@ -232,7 +232,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } if( CharArrayUtils.equals( c, compName.toCharArray() ) ){ if( isConstructorReference( name ) ){ - return CPPSemantics.resolveAmbiguities( name, getConstructors( bindings, resolve ) ); + return CPPSemantics.resolveAmbiguities( name, getConstructors( bindings, resolve, name ) ); } //9.2 ... The class-name is also inserted into the scope of the class itself return compName.resolveBinding(); @@ -240,10 +240,23 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { return super.getBinding( name, resolve ); } - protected ICPPConstructor [] getConstructors( boolean forceResolve ){ - return getConstructors( bindings, forceResolve ); + static protected boolean shouldResolve(boolean force, IASTName candidate, IASTName forName) { + if(!force || candidate == forName) + return false; + if(forName == null) + return true; + if(!forName.isReference() && !CPPSemantics.declaredBefore(candidate, forName)) + return false; + return true; } - static protected ICPPConstructor [] getConstructors( CharArrayObjectMap bindings, boolean forceResolve ){ + + protected ICPPConstructor [] getConstructors( boolean forceResolve ){ + return getConstructors( bindings, forceResolve, null ); + } + static protected ICPPConstructor [] getConstructors( CharArrayObjectMap bindings, boolean forceResolve ) { + return getConstructors(bindings, forceResolve, null); + } + static protected ICPPConstructor [] getConstructors( CharArrayObjectMap bindings, boolean forceResolve, IASTName forName ){ if( bindings == null ) return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY; @@ -256,8 +269,8 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { for( int i = 0; i < set.size(); i++ ){ Object obj = set.keyAt( i ); if( obj instanceof IASTName ){ - IASTName n = (IASTName) obj; - binding = forceResolve ? n.resolveBinding() : n.getBinding(); + IASTName n = (IASTName) obj; + binding = shouldResolve(forceResolve, n, forName) ? n.resolveBinding() : n.getBinding(); if( binding != null ) { set.remove( n ); set.put( binding ); @@ -269,7 +282,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope { } return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, bs ); } else if( o instanceof IASTName ){ - if( forceResolve || ((IASTName)o).getBinding() != null ){ + if( shouldResolve(forceResolve, (IASTName) o, forName) || ((IASTName)o).getBinding() != null ){ binding = ((IASTName)o).resolveBinding(); bindings.put( CONSTRUCTOR_KEY, binding ); }