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:
parent
10b6e03e06
commit
6fa2b47130
4 changed files with 153 additions and 19 deletions
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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(){
|
||||
|
|
|
@ -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 ) {
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue