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 );
}
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;
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.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IField;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
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.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.ICPPClassTemplate;
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.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
/**
* @author aniefer
@ -39,6 +49,52 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
public class CPPClassTemplate extends CPPTemplateDefinition implements
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
*/
@ -55,17 +111,18 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
return instance;
}
private void checkForDefinition(){
// CPPClassType.FindDefinitionAction action = new FindDefinitionAction();
// IASTNode node = CPPVisitor.getContainingBlockItem( getPhysicalNode() ).getParent();
//
// node.accept( action );
// definition = action.result;
//
// if( definition == null ){
// node.getTranslationUnit().accept( action );
// definition = action.result;
// }
//
FindDefinitionAction action = new FindDefinitionAction();
IASTNode node = CPPVisitor.getContainingBlockItem( declarations[0] ).getParent();
while( node instanceof ICPPASTTemplateDeclaration )
node = node.getParent();
node.accept( action );
definition = action.result;
if( definition == null ){
node.getTranslationUnit().accept( action );
definition = action.result;
}
return;
}
private ICPPASTCompositeTypeSpecifier getCompositeTypeSpecifier(){
@ -191,8 +248,17 @@ public class CPPClassTemplate extends CPPTemplateDefinition implements
* @see org.eclipse.cdt.core.dom.ast.ICompositeType#getKey()
*/
public int getKey() {
// TODO Auto-generated method stub
return 0;
if( definition != null )
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)

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.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.ICPPASTUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBlockScope;
@ -206,12 +207,24 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType {
shouldVisitDeclarations = true;
shouldVisitDeclSpecifiers = true;
shouldVisitDeclarators = true;
shouldVisitNamespaces = true;
}
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 &&
CharArrayUtils.equals( name.toCharArray(), nameArray ) )
CharArrayUtils.equals( c, nameArray ) )
{
IBinding binding = name.resolveBinding();
if( binding == CPPClassType.this ){
@ -228,7 +241,7 @@ public class CPPClassType implements ICPPClassType, ICPPInternalClassType {
public int visit( IASTDeclSpecifier declSpec ){
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(){

View file

@ -527,9 +527,19 @@ public class CPPSemantics {
ASTNodeProperty prop = data.astName.getPropertyInParent();
if( prop != ICPPASTQualifiedName.SEGMENT_NAME && prop != ICPPASTTemplateId.TEMPLATE_NAME ){
try {
IScope scope = ((ICPPClassType)binding).getCompositeScope();
if( CPPVisitor.getContainingScope( data.astName ) == scope ){
binding = CPPTemplates.instantiateWithinClassTemplate( (ICPPClassTemplate) binding );
IASTNode def = ((ICPPInternalBinding)binding).getDefinition();
if( def != null ){
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 ) {
}