1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

template fixes

- instantiating a template within itself
- finding the definiition of a class template
This commit is contained in:
Andrew Niefer 2005-04-28 20:34:27 +00:00
parent 10b6e03e06
commit 6fa2b47130
4 changed files with 153 additions and 19 deletions

View file

@ -875,4 +875,49 @@ public class AST2TemplateTests extends AST2BaseTest {
assertInstances( col, T1, 4 ); assertInstances( col, T1, 4 );
} }
public void testDeferredInstantiation() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template < class T > class A { \n"); //$NON-NLS-1$
buffer.append(" int f( A * ); \n"); //$NON-NLS-1$
buffer.append(" A < T > *pA; \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("void f () { \n"); //$NON-NLS-1$
buffer.append(" A< int > *a; \n"); //$NON-NLS-1$
buffer.append(" a->f( a ); \n"); //$NON-NLS-1$
buffer.append(" a->pA; \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPClassTemplate A = (ICPPClassTemplate) col.getName(1).resolveBinding();
ICPPMethod f = (ICPPMethod) col.getName(2).resolveBinding();
ICPPClassType A1 = (ICPPClassType) col.getName(3).resolveBinding();
ICPPClassType A2 = (ICPPClassType) col.getName(5).resolveBinding();
ICPPField pA = (ICPPField) col.getName(8).resolveBinding();
assertSame( A1, A2 );
assertTrue( A1 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A1).getOriginalBinding(), A );
ICPPClassType AI = (ICPPClassType) col.getName(10).resolveBinding();
ICPPMethod f2 = (ICPPMethod) col.getName(14).resolveBinding();
ICPPField pA2 = (ICPPField) col.getName(17).resolveBinding();
assertTrue( f2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)f2).getOriginalBinding(), f );
assertTrue( pA2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)pA2).getOriginalBinding(), pA );
IType paT = pA2.getType();
assertTrue( paT instanceof IPointerType );
assertSame( ((IPointerType)paT).getType(), AI );
IParameter p = f2.getParameters()[0];
IType pT = p.getType();
assertTrue( pT instanceof IPointerType );
assertSame( ((IPointerType)pT).getType(), AI );
}
} }

View file

@ -14,15 +14,24 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp; package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField; import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.CPPASTVisitor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
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.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
@ -32,6 +41,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
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.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
/** /**
* @author aniefer * @author aniefer
@ -39,6 +49,52 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
public class CPPClassTemplate extends CPPTemplateDefinition implements public class CPPClassTemplate extends CPPTemplateDefinition implements
ICPPClassTemplate, ICPPClassType, ICPPInternalClassType { ICPPClassTemplate, ICPPClassType, ICPPInternalClassType {
private class FindDefinitionAction extends CPPASTVisitor {
private char [] nameArray = CPPClassTemplate.this.getNameCharArray();
public IASTName result = null;
{
shouldVisitNames = true;
shouldVisitDeclarations = true;
shouldVisitDeclSpecifiers = true;
shouldVisitDeclarators = true;
}
public int visit( IASTName name ){
if( name instanceof ICPPASTTemplateId || name instanceof ICPPASTQualifiedName )
return PROCESS_CONTINUE;
char [] c = name.toCharArray();
if( name.getParent() instanceof ICPPASTTemplateId )
name = (IASTName) name.getParent();
if( name.getParent() instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)name.getParent()).getNames();
if( ns[ ns.length - 1 ] != name )
return PROCESS_CONTINUE;
name = (IASTName) name.getParent();
}
if( name.getParent() instanceof ICPPASTCompositeTypeSpecifier &&
CharArrayUtils.equals( c, nameArray ) )
{
IBinding binding = name.resolveBinding();
if( binding == CPPClassTemplate.this ){
result = name;
return PROCESS_ABORT;
}
}
return PROCESS_CONTINUE;
}
public int visit( IASTDeclaration declaration ){
if(declaration instanceof IASTSimpleDeclaration || declaration instanceof ICPPASTTemplateDeclaration )
return PROCESS_CONTINUE;
return PROCESS_SKIP;
}
public int visit( IASTDeclSpecifier declSpec ){
return (declSpec instanceof ICPPASTCompositeTypeSpecifier ) ? PROCESS_CONTINUE : PROCESS_SKIP;
}
public int visit( IASTDeclarator declarator ) { return PROCESS_SKIP; }
}
/** /**
* @param decl * @param decl
*/ */
@ -55,17 +111,18 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
return instance; return instance;
} }
private void checkForDefinition(){ private void checkForDefinition(){
// CPPClassType.FindDefinitionAction action = new FindDefinitionAction(); FindDefinitionAction action = new FindDefinitionAction();
// IASTNode node = CPPVisitor.getContainingBlockItem( getPhysicalNode() ).getParent(); IASTNode node = CPPVisitor.getContainingBlockItem( declarations[0] ).getParent();
// while( node instanceof ICPPASTTemplateDeclaration )
// node.accept( action ); node = node.getParent();
// definition = action.result; node.accept( action );
// definition = action.result;
// if( definition == null ){
// node.getTranslationUnit().accept( action ); if( definition == null ){
// definition = action.result; node.getTranslationUnit().accept( action );
// } definition = action.result;
// }
return; return;
} }
private ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier(){ private ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier(){
@ -191,8 +248,17 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getKey() * @see org.eclipse.cdt.core.dom.ast.ICompositeType#getKey()
*/ */
public int getKey() { public int getKey() {
// TODO Auto-generated method stub if( definition != null )
return 0; return getCompositeTypeSpecifier().getKey();
if( declarations != null && declarations.length > 0 ){
IASTNode n = declarations[0].getParent();
if( n instanceof ICPPASTElaboratedTypeSpecifier ){
return ((ICPPASTElaboratedTypeSpecifier)n).getKind();
}
}
return ICPPASTElaboratedTypeSpecifier.k_class;
} }
/* (non-Javadoc) /* (non-Javadoc)

View file

@ -36,6 +36,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
@ -206,12 +207,24 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType {
shouldVisitDeclarations = true; shouldVisitDeclarations = true;
shouldVisitDeclSpecifiers = true; shouldVisitDeclSpecifiers = true;
shouldVisitDeclarators = true; shouldVisitDeclarators = true;
shouldVisitNamespaces = true;
} }
public int visit( IASTName name ){ public int visit( IASTName name ){
if( name instanceof ICPPASTTemplateId )
return PROCESS_SKIP;
if( name instanceof ICPPASTQualifiedName )
return PROCESS_CONTINUE;
char [] c = name.toCharArray();
if( name.getParent() instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)name.getParent()).getNames();
if( ns[ ns.length - 1 ] != name )
return PROCESS_CONTINUE;
name = (IASTName) name.getParent();
}
if( name.getParent() instanceof ICPPASTCompositeTypeSpecifier && if( name.getParent() instanceof ICPPASTCompositeTypeSpecifier &&
CharArrayUtils.equals( name.toCharArray(), nameArray ) ) CharArrayUtils.equals( c, nameArray ) )
{ {
IBinding binding = name.resolveBinding(); IBinding binding = name.resolveBinding();
if( binding == CPPClassType.this ){ if( binding == CPPClassType.this ){
@ -228,7 +241,7 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType {
public int visit( IASTDeclSpecifier declSpec ){ public int visit( IASTDeclSpecifier declSpec ){
return (declSpec instanceof ICPPASTCompositeTypeSpecifier ) ? PROCESS_CONTINUE : PROCESS_SKIP; return (declSpec instanceof ICPPASTCompositeTypeSpecifier ) ? PROCESS_CONTINUE : PROCESS_SKIP;
} }
public int processDeclarators( IASTDeclarator declarator ) { return PROCESS_SKIP; } public int visit( IASTDeclarator declarator ) { return PROCESS_SKIP; }
} }
private void checkForDefinition(){ private void checkForDefinition(){

View file

@ -527,9 +527,19 @@ public class CPPSemantics {
ASTNodeProperty prop = data.astName.getPropertyInParent(); ASTNodeProperty prop = data.astName.getPropertyInParent();
if( prop != ICPPASTQualifiedName.SEGMENT_NAME && prop != ICPPASTTemplateId.TEMPLATE_NAME ){ if( prop != ICPPASTQualifiedName.SEGMENT_NAME && prop != ICPPASTTemplateId.TEMPLATE_NAME ){
try { try {
IScope scope = ((ICPPClassType)binding).getCompositeScope(); IASTNode def = ((ICPPInternalBinding)binding).getDefinition();
if( CPPVisitor.getContainingScope( data.astName ) == scope ){ if( def != null ){
binding = CPPTemplates.instantiateWithinClassTemplate( (ICPPClassTemplate) binding ); def = def.getParent();
IASTNode parent = data.astName.getParent();
while( parent != null ){
if( parent == def ){
binding = CPPTemplates.instantiateWithinClassTemplate( (ICPPClassTemplate) binding );
break;
}
if( parent instanceof ICPPASTNamespaceDefinition )
break;
parent = parent.getParent();
}
} }
} catch( DOMException e ) { } catch( DOMException e ) {
} }