mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
fix bug 103715 and partial for 98171 (getBases)
This commit is contained in:
parent
0fdbe3e9c4
commit
c683a357d4
11 changed files with 128 additions and 69 deletions
|
@ -500,35 +500,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.8.3-4):
|
||||
template<class T> struct B { };
|
||||
template<class T> struct D : public B<T> { };
|
||||
template<class T> void f(B<T>&);
|
||||
void g(B<int>& bi, D<int>& di)
|
||||
{
|
||||
f(bi); // f(bi)
|
||||
f(di); // f( (B<int>&)di )
|
||||
}
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_8_3s4() {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T> struct B { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> struct D : public B<T> { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(B<T>&);\n"); //$NON-NLS-1$
|
||||
buffer.append("void g(B<int>& bi, D<int>& 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<int>&)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
|
||||
|
|
|
@ -11213,6 +11213,31 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
[--Start Example(CPP 14.8.3-4):
|
||||
template<class T> struct B { };
|
||||
template<class T> struct D : public B<T> { };
|
||||
template<class T> void f(B<T>&);
|
||||
void g(B<int>& bi, D<int>& di)
|
||||
{
|
||||
f(bi); // f(bi)
|
||||
f(di); // f( (B<int>&)di )
|
||||
}
|
||||
--End Example]
|
||||
*/
|
||||
public void test14_8_3s4() throws Exception {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
buffer.append("template<class T> struct B { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> struct D : public B<T> { };\n"); //$NON-NLS-1$
|
||||
buffer.append("template<class T> void f(B<T>&);\n"); //$NON-NLS-1$
|
||||
buffer.append("void g(B<int>& bi, D<int>& 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<int>&)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):
|
||||
|
|
|
@ -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 T> 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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue