diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java index c15f2a5ea50..86ed3860b5e 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java @@ -500,35 +500,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { } } - /** - [--Start Example(CPP 14.8.3-4): - template struct B { }; - template struct D : public B { }; - template void f(B&); - void g(B& bi, D& di) - { - f(bi); // f(bi) - f(di); // f( (B&)di ) - } - --End Example] - */ - public void test14_8_3s4() { - StringBuffer buffer = new StringBuffer(); - buffer.append("template struct B { };\n"); //$NON-NLS-1$ - buffer.append("template struct D : public B { };\n"); //$NON-NLS-1$ - buffer.append("template void f(B&);\n"); //$NON-NLS-1$ - buffer.append("void g(B& bi, D& di)\n"); //$NON-NLS-1$ - buffer.append("{\n"); //$NON-NLS-1$ - buffer.append("f(bi); // f(bi)\n"); //$NON-NLS-1$ - buffer.append("f(di); // f( (B&)di )\n"); //$NON-NLS-1$ - buffer.append("}\n"); //$NON-NLS-1$ - try { - parse(buffer.toString(), ParserLanguage.CPP, true, 0); - assertTrue(false); - } catch (Exception e) { - } - } - /** [--Start Example(CPP 14.5.5.1-8a): // Guaranteed to be the same diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index fc08ec7d7c4..a7281027270 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -11213,6 +11213,31 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(buffer.toString(), ParserLanguage.CPP, true, 0); } + /** + [--Start Example(CPP 14.8.3-4): + template struct B { }; + template struct D : public B { }; + template void f(B&); + void g(B& bi, D& di) + { + f(bi); // f(bi) + f(di); // f( (B&)di ) + } + --End Example] + */ + public void test14_8_3s4() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template struct B { };\n"); //$NON-NLS-1$ + buffer.append("template struct D : public B { };\n"); //$NON-NLS-1$ + buffer.append("template void f(B&);\n"); //$NON-NLS-1$ + buffer.append("void g(B& bi, D& di)\n"); //$NON-NLS-1$ + buffer.append("{\n"); //$NON-NLS-1$ + buffer.append("f(bi); // f(bi)\n"); //$NON-NLS-1$ + buffer.append("f(di); // f( (B&)di )\n"); //$NON-NLS-1$ + buffer.append("}\n"); //$NON-NLS-1$ + + parse(buffer.toString(), ParserLanguage.CPP, true, 0); + } /** [--Start Example(CPP 14.8.3-6): 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 b9c6f1415e3..9d61c041d31 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 @@ -33,6 +33,7 @@ import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization; @@ -1846,4 +1847,28 @@ public class AST2TemplateTests extends AST2BaseTest { assertSame( ((ICPPTemplateInstance)a).getTemplateDefinition(), A ); assertSame( local, col.getName(7).resolveBinding() ); } + + public void testBug103715() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template class A : public T {}; \n"); //$NON-NLS-1$ + buffer.append("class B { int base; }; \n"); //$NON-NLS-1$ + buffer.append("void f() { \n"); //$NON-NLS-1$ + buffer.append(" A< B > a; \n"); //$NON-NLS-1$ + buffer.append(" a.base; \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 ); + + ICPPField base = (ICPPField) col.getName(4).resolveBinding(); + assertSame( base, col.getName(11).resolveBinding() ); + + ICPPClassType B = (ICPPClassType) col.getName(3).resolveBinding(); + ICPPClassType A = (ICPPClassType) col.getName(6).resolveBinding(); + + ICPPBase [] bases = A.getBases(); + assertEquals( bases.length, 1 ); + assertSame( bases[0].getBaseClass(), B ); + } } diff --git a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/domsourceindexer/CPPGenerateIndexVisitor.java b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/domsourceindexer/CPPGenerateIndexVisitor.java index e56631e0ae8..243577cf260 100644 --- a/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/domsourceindexer/CPPGenerateIndexVisitor.java +++ b/core/org.eclipse.cdt.core/index/org/eclipse/cdt/internal/core/index/domsourceindexer/CPPGenerateIndexVisitor.java @@ -353,7 +353,10 @@ public class CPPGenerateIndexVisitor extends CPPASTVisitor { ICPPBase[] baseClasses = cppClassBinding.getBases(); for (int i = 0; i < baseClasses.length; i++) { ICPPBase base = baseClasses[i]; - ICPPClassType baseClass = baseClasses[i].getBaseClass(); + IBinding b = baseClasses[i].getBaseClass(); + if( !(b instanceof ICPPClassType) ) + continue; + ICPPClassType baseClass = (ICPPClassType) b; // skip problem bindings if (baseClass instanceof IProblemBinding) continue; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java index e9fd6a12a80..68909aba9b2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPBase.java @@ -11,6 +11,7 @@ package org.eclipse.cdt.core.dom.ast.cpp; import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; /** @@ -22,11 +23,13 @@ public interface ICPPBase { public static final ICPPBase[] EMPTY_BASE_ARRAY = new ICPPBase[0]; /** - * The base class. + * The base class. Generally a ICPPClassType, but may be a ICPPTemplateParameter. + * In the case of typedefs, the binding being typedefed will be returned instead of + * the typedef itself. * * @return */ - public ICPPClassType getBaseClass() throws DOMException; + public IBinding getBaseClass() throws DOMException; /** * The visibility qualifier applied to the base class. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java index 10dfd1618fc..6e26b45da3d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBaseClause.java @@ -18,9 +18,11 @@ import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding; @@ -33,7 +35,7 @@ public class CPPBaseClause implements ICPPBase { public CPPBaseProblem( IASTNode node, int id, char[] arg ) { super( node, id, arg ); } - public ICPPClassType getBaseClass() { + public IBinding getBaseClass() { if( classProblem == null ){ classProblem = new CPPClassType.CPPClassTypeProblem( node, id, arg ); } @@ -49,7 +51,7 @@ public class CPPBaseClause implements ICPPBase { } } private ICPPASTBaseSpecifier base = null; - private ICPPClassType baseClass = null; + private IBinding baseClass = null; public CPPBaseClause( ICPPASTBaseSpecifier base ){ this.base = base; @@ -58,11 +60,15 @@ public class CPPBaseClause implements ICPPBase { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPBase#getBaseClass() */ - public ICPPClassType getBaseClass() { + public IBinding getBaseClass() throws DOMException { if( baseClass == null ){ IBinding b = base.getName().resolveBinding(); - if( b instanceof ICPPClassType ) - baseClass = (ICPPClassType) b; + while( b instanceof ITypedef && ((ITypedef)b).getType() instanceof IBinding ){ + b = (IBinding) ((ITypedef)b).getType(); + } + if( b instanceof ICPPClassType || b instanceof ICPPTemplateParameter ) + baseClass = b; + else if( b instanceof IProblemBinding ){ baseClass = new CPPClassType.CPPClassTypeProblem( base.getName(), ((IProblemBinding)b).getID(), base.getName().toCharArray() ); } else { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java index 7dd40283b52..760f98d3162 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassInstance.java @@ -28,6 +28,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.parser.util.ObjectMap; /** @@ -48,7 +49,20 @@ public class CPPClassInstance extends CPPInstance implements ICPPClassType, ICPP /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType#getBases() */ - public ICPPBase[] getBases() { + public ICPPBase[] getBases() throws DOMException { + ICPPClassType cls = (ICPPClassType) getSpecializedBinding(); + if( cls != null ){ + ICPPBase [] bases = cls.getBases(); + for (int i = 0; i < bases.length; i++) { + IBinding T = bases[i].getBaseClass(); + if( T instanceof ICPPTemplateTypeParameter && argumentMap.containsKey( T ) ){ + IType t = (IType) argumentMap.get( T ); + if( t instanceof ICPPClassType ) + ((CPPBaseClause)bases[i]).setBaseClass( (ICPPClassType) argumentMap.get(T) ); + } + } + return bases; + } return ICPPBase.EMPTY_BASE_ARRAY; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java index b26497527ae..376f25ac9b4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecialization.java @@ -55,7 +55,7 @@ public class CPPClassSpecialization extends CPPSpecialization implements if( cls != null ){ ICPPBase [] bases = cls.getBases(); for (int i = 0; i < bases.length; i++) { - ICPPClassType T = bases[i].getBaseClass(); + IBinding T = bases[i].getBaseClass(); if( T instanceof ICPPTemplateTypeParameter && argumentMap.containsKey( T ) ){ IType t = (IType) argumentMap.get( T ); if( t instanceof ICPPClassType ) @@ -64,7 +64,6 @@ public class CPPClassSpecialization extends CPPSpecialization implements } return bases; } - // TODO Auto-generated method stub return ICPPBase.EMPTY_BASE_ARRAY; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java index 247d23d421c..87feb49d90f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassTemplate.java @@ -218,7 +218,9 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements IField[] fields = getDeclaredFields(); ICPPBase [] bases = getBases(); for ( int i = 0; i < bases.length; i++ ) { - fields = (IField[]) ArrayUtil.addAll( IField.class, fields, bases[i].getBaseClass().getFields() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + fields = (IField[]) ArrayUtil.addAll( IField.class, fields, ((ICPPClassType)b).getFields() ); } return (IField[]) ArrayUtil.trim( IField.class, fields ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java index 5176f8b019b..bdbace3468f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassType.java @@ -317,7 +317,9 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { IField[] fields = getDeclaredFields(); ICPPBase [] bases = getBases(); for ( int i = 0; i < bases.length; i++ ) { - fields = (IField[]) ArrayUtil.addAll( IField.class, fields, bases[i].getBaseClass().getFields() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + fields = (IField[]) ArrayUtil.addAll( IField.class, fields, ((ICPPClassType)b).getFields() ); } return (IField[]) ArrayUtil.trim( IField.class, fields ); } @@ -548,14 +550,16 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { ICPPBase [] bases = getBases(); for ( int i = 0; i < bases.length; i++ ) { - ICPPClassType cls; + ICPPClassType cls = null; try { - cls = bases[i].getBaseClass(); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + cls = (ICPPClassType) b; } catch (DOMException e) { continue; } - if( cls instanceof CPPClassType ) - result = (ICPPMethod[]) ArrayUtil.addAll( ICPPMethod.class, result, ((CPPClassType)cls).getConversionOperators() ); + if( cls instanceof ICPPInternalClassType ) + result = (ICPPMethod[]) ArrayUtil.addAll( ICPPMethod.class, result, ((ICPPInternalClassType)cls).getConversionOperators() ); } return (ICPPMethod[]) ArrayUtil.trim( ICPPMethod.class, result ); } @@ -571,7 +575,9 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { set.addAll( scope.getImplicitMethods() ); ICPPBase [] bases = getBases(); for ( int i = 0; i < bases.length; i++ ) { - set.addAll( bases[i].getBaseClass().getMethods() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + set.addAll( ((ICPPClassType)b).getMethods() ); } return (ICPPMethod[]) set.keyArray( ICPPMethod.class ); } @@ -591,7 +597,9 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType { ICPPMethod[] methods = getDeclaredMethods(); ICPPBase [] bases = getBases(); for ( int i = 0; i < bases.length; i++ ) { - methods = (ICPPMethod[]) ArrayUtil.addAll( ICPPMethod.class, methods, bases[i].getBaseClass().getAllDeclaredMethods() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + methods = (ICPPMethod[]) ArrayUtil.addAll( ICPPMethod.class, methods, ((ICPPClassType)b).getAllDeclaredMethods() ); } return (ICPPMethod[]) ArrayUtil.trim( ICPPMethod.class, methods ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 61c48ca41f8..e2c827f5988 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -852,7 +852,9 @@ public class CPPSemantics { for( int i = 0; i < bases.length; i++ ){ if( bases[i] instanceof IProblemBinding ) continue; - getAssociatedScopes( bases[i].getBaseClass(), namespaces, classes ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof IType ) + getAssociatedScopes( (IType) b, namespaces, classes ); } } } else if( t instanceof IEnumeration ){ @@ -1094,12 +1096,11 @@ public class CPPSemantics { } private static Object lookupInParents( CPPSemantics.LookupData data, ICPPScope lookIn ) throws DOMException{ - IASTNode node = lookIn.getPhysicalNode(); - if( node == null || !(node instanceof ICPPASTCompositeTypeSpecifier) ) - return null; - - ICPPASTCompositeTypeSpecifier compositeTypeSpec = (ICPPASTCompositeTypeSpecifier) node; - ICPPASTBaseSpecifier [] bases = compositeTypeSpec.getBaseSpecifiers(); + ICPPBase [] bases = null; + if( lookIn instanceof ICPPClassScope ){ + ICPPClassType c = ((ICPPClassScope)lookIn).getClassType(); + bases = c.getBases(); + } Object inherited = null; Object result = null; @@ -1118,12 +1119,9 @@ public class CPPSemantics { { inherited = null; ICPPClassType cls = null; - IBinding binding = bases[i].getName().resolveBinding(); - while( binding instanceof ITypedef && ((ITypedef)binding).getType() instanceof IBinding ){ - binding = (IBinding) ((ITypedef)binding).getType(); - } - if( binding instanceof ICPPClassType ) - cls = (ICPPClassType) binding; + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + cls = (ICPPClassType) b; else continue; ICPPScope parent = (ICPPScope) cls.getCompositeScope(); @@ -1159,7 +1157,7 @@ public class CPPSemantics { visitVirtualBaseClasses( data, cls ); } } else { - data.problem = new ProblemBinding( bases[i].getName(), IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, bases[i].getName().toCharArray() ); + data.problem = new ProblemBinding( null, IProblemBinding.SEMANTIC_CIRCULAR_INHERITANCE, cls.getNameCharArray() ); return null; } } @@ -1218,9 +1216,13 @@ public class CPPSemantics { if( bases[i].isVirtual() ){ if( data.visited == ObjectSet.EMPTY_SET ) data.visited = new ObjectSet(2); - data.visited.put( bases[i].getBaseClass().getCompositeScope() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + data.visited.put( ((ICPPClassType)b).getCompositeScope() ); } else { - visitVirtualBaseClasses( data, bases[i].getBaseClass() ); + IBinding b = bases[i].getBaseClass(); + if( b instanceof ICPPClassType ) + visitVirtualBaseClasses( data, (ICPPClassType) b ); } } catch ( DOMException e1 ) { } @@ -3104,17 +3106,18 @@ public class CPPSemantics { else return -1; - ICPPClassType parent = null; + IBinding parent = null; ICPPBase [] bases = clsSymbol.getBases(); for( int i = 0; i < bases.length; i ++ ){ ICPPBase wrapper = bases[i]; parent = bases[i].getBaseClass(); boolean isVisible = ( wrapper.getVisibility() == ICPPBase.v_public); - - if( parent.isSameType( clsBase ) || - (clsBase instanceof ICPPSpecialization && //allow some flexibility with templates - ((IType)((ICPPSpecialization)clsBase).getSpecializedBinding()).isSameType( parent ) ) ) + + if( parent instanceof IType && + ( ((IType)parent).isSameType( clsBase ) || + ( clsBase instanceof ICPPSpecialization && //allow some flexibility with templates + ((IType)((ICPPSpecialization)clsBase).getSpecializedBinding()).isSameType( (IType) parent ) ) ) ) { if( needVisibility && !isVisible ) return -1;