mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 162230 - Fix a stack overflow that was happening with function template specializations.
This commit is contained in:
parent
494ab7d964
commit
58a835d441
3 changed files with 65 additions and 8 deletions
|
@ -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.ICPPFunction;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
|
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.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.ICPPSpecialization;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
|
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();
|
ICPPVariable c = (ICPPVariable) col.getName(13).resolveBinding();
|
||||||
assertSame( c, col.getName(4).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<typename G> 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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ public class CPPClassInstanceScope implements ICPPClassScope, IASTInternalScope
|
||||||
if( instanceMap.containsKey( n ) ){
|
if( instanceMap.containsKey( n ) ){
|
||||||
binding = (IBinding) instanceMap.get( n );
|
binding = (IBinding) instanceMap.get( n );
|
||||||
} else {
|
} else {
|
||||||
binding = forceResolve ? n.resolveBinding() : n.getBinding();
|
binding = CPPClassScope.shouldResolve(forceResolve, n, name) ? n.resolveBinding() : n.getBinding();
|
||||||
if (binding instanceof ICPPClassTemplatePartialSpecialization ){
|
if (binding instanceof ICPPClassTemplatePartialSpecialization ){
|
||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,7 +232,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
}
|
}
|
||||||
if( CharArrayUtils.equals( c, compName.toCharArray() ) ){
|
if( CharArrayUtils.equals( c, compName.toCharArray() ) ){
|
||||||
if( isConstructorReference( name ) ){
|
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
|
//9.2 ... The class-name is also inserted into the scope of the class itself
|
||||||
return compName.resolveBinding();
|
return compName.resolveBinding();
|
||||||
|
@ -240,10 +240,23 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
return super.getBinding( name, resolve );
|
return super.getBinding( name, resolve );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ICPPConstructor [] getConstructors( boolean forceResolve ){
|
static protected boolean shouldResolve(boolean force, IASTName candidate, IASTName forName) {
|
||||||
return getConstructors( bindings, forceResolve );
|
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 )
|
if( bindings == null )
|
||||||
return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;
|
return ICPPConstructor.EMPTY_CONSTRUCTOR_ARRAY;
|
||||||
|
|
||||||
|
@ -256,8 +269,8 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
for( int i = 0; i < set.size(); i++ ){
|
for( int i = 0; i < set.size(); i++ ){
|
||||||
Object obj = set.keyAt( i );
|
Object obj = set.keyAt( i );
|
||||||
if( obj instanceof IASTName ){
|
if( obj instanceof IASTName ){
|
||||||
IASTName n = (IASTName) obj;
|
IASTName n = (IASTName) obj;
|
||||||
binding = forceResolve ? n.resolveBinding() : n.getBinding();
|
binding = shouldResolve(forceResolve, n, forName) ? n.resolveBinding() : n.getBinding();
|
||||||
if( binding != null ) {
|
if( binding != null ) {
|
||||||
set.remove( n );
|
set.remove( n );
|
||||||
set.put( binding );
|
set.put( binding );
|
||||||
|
@ -269,7 +282,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
|
||||||
}
|
}
|
||||||
return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, bs );
|
return (ICPPConstructor[]) ArrayUtil.trim( ICPPConstructor.class, bs );
|
||||||
} else if( o instanceof IASTName ){
|
} 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();
|
binding = ((IASTName)o).resolveBinding();
|
||||||
bindings.put( CONSTRUCTOR_KEY, binding );
|
bindings.put( CONSTRUCTOR_KEY, binding );
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue