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

handle template explicit instantiations. fixes bug 90689

also fix small bug in template argument deduction
This commit is contained in:
Andrew Niefer 2005-05-10 14:40:37 +00:00
parent 509ee1af20
commit e2e8b4439d
5 changed files with 192 additions and 108 deletions

View file

@ -587,97 +587,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
} }
} }
/**
[--Start Example(CPP 14.7.2-2):
template<class T> class Array { void mf(); };
template class Array<char>;
template void Array<int>::mf();
template<class T> void sort(Array<T>& v) { }
template void sort(Array<char>&); // argument is deduced here
namespace N {
template<class T> void f(T&) { }
}
template void N::f<int>(int&);
--End Example]
*/
public void test14_7_2s2() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { void mf(); };\n"); //$NON-NLS-1$
buffer.append("template class Array<char>;\n"); //$NON-NLS-1$
buffer.append("template void Array<int>::mf();\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v) { }\n"); //$NON-NLS-1$
buffer.append("template void sort(Array<char>&); // argument is deduced here\n"); //$NON-NLS-1$
buffer.append("namespace N {\n"); //$NON-NLS-1$
buffer.append("template<class T> void f(T&) { }\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
buffer.append("template void N::f<int>(int&);\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 3);
}
/**
[--Start Example(CPP 14.7.2-6):
template<class T> class Array { };
template<class T> void sort(Array<T>& v);
// instantiate sort(Array<int>&) - templateargument deduced
template void sort<>(Array<int>&);
--End Example]
*/
public void test14_7_2s6() { // TODO raised bug 90689
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v);\n"); //$NON-NLS-1$
buffer.append("// instantiate sort(Array<int>&) - templateargument deduced\n"); //$NON-NLS-1$
buffer.append("template void sort<>(Array<int>&);\n"); //$NON-NLS-1$
try {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
assertTrue(false);
} catch (Exception e) {
}
}
/**
[--Start Example(CPP 14.7.3-1):
template<class T> class stream;
template<> class stream<char> { };
template<class T> class Array { };
template<class T> void sort(Array<T>& v) { }
template<> void sort<char*>(Array<char*>&) ;
--End Example]
*/
public void test14_7_3s1() { // TODO have similar bug
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class stream;\n"); //$NON-NLS-1$
buffer.append("template<> class stream<char> { };\n"); //$NON-NLS-1$
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v) { }\n"); //$NON-NLS-1$
buffer.append("template<> void sort<char*>(Array<char*>&) ;\n"); //$NON-NLS-1$
try {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
assertTrue(false);
} catch (Exception e) {
}
}
/**
[--Start Example(CPP 14.7.3-11):
template<class T> class Array { };
template<class T> void sort(Array<T>& v);
// explicit specialization for sort(Array<int>&)
// with deduces templateargument of type int
template<> void sort(Array<int>&);
--End Example]
*/
public void test14_7_3s11() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v);\n"); //$NON-NLS-1$
buffer.append("// explicit specialization for sort(Array<int>&)\n"); //$NON-NLS-1$
buffer.append("// with deduces templateargument of type int\n"); //$NON-NLS-1$
buffer.append("template<> void sort(Array<int>&);\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 1);
}
/** /**
[--Start Example(CPP 14.8.2-2b): [--Start Example(CPP 14.8.2-2b):
template <class T> int f(typename T::B*); template <class T> int f(typename T::B*);

View file

@ -10224,6 +10224,33 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 0); parse(buffer.toString(), ParserLanguage.CPP, true, 0);
} }
/**
[--Start Example(CPP 14.7.2-2):
template<class T> class Array { void mf(); };
template class Array<char>;
template void Array<int>::mf();
template<class T> void sort(Array<T>& v) { }
template void sort(Array<char>&); // argument is deduced here
namespace N {
template<class T> void f(T&) { }
}
template void N::f<int>(int&);
--End Example]
*/
public void test14_7_2s2() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { void mf(); };\n"); //$NON-NLS-1$
buffer.append("template class Array<char>;\n"); //$NON-NLS-1$
buffer.append("template void Array<int>::mf();\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v) { }\n"); //$NON-NLS-1$
buffer.append("template void sort(Array<char>&); // argument is deduced here\n"); //$NON-NLS-1$
buffer.append("namespace N {\n"); //$NON-NLS-1$
buffer.append("template<class T> void f(T&) { }\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
buffer.append("template void N::f<int>(int&);\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/** /**
[--Start Example(CPP 14.7.2-5): [--Start Example(CPP 14.7.2-5):
namespace N { namespace N {
@ -10253,6 +10280,24 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, false, 0); parse(buffer.toString(), ParserLanguage.CPP, false, 0);
} }
/**
[--Start Example(CPP 14.7.2-6):
template<class T> class Array { };
template<class T> void sort(Array<T>& v);
// instantiate sort(Array<int>&) - templateargument deduced
template void sort<>(Array<int>&);
--End Example]
*/
public void test14_7_2s6() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v);\n"); //$NON-NLS-1$
buffer.append("// instantiate sort(Array<int>&) - templateargument deduced\n"); //$NON-NLS-1$
buffer.append("template void sort<>(Array<int>&);\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/** /**
[--Start Example(CPP 14.7.2-9): [--Start Example(CPP 14.7.2-9):
char* p = 0; char* p = 0;
@ -10268,6 +10313,26 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 0); parse(buffer.toString(), ParserLanguage.CPP, true, 0);
} }
/**
[--Start Example(CPP 14.7.3-1):
template<class T> class stream;
template<> class stream<char> { };
template<class T> class Array { };
template<class T> void sort(Array<T>& v) { }
template<> void sort<char*>(Array<char*>&) ;
--End Example]
*/
public void test14_7_3s1() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class stream;\n"); //$NON-NLS-1$
buffer.append("template<> class stream<char> { };\n"); //$NON-NLS-1$
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v) { }\n"); //$NON-NLS-1$
buffer.append("template<> void sort<char*>(Array<char*>&) ;\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/** /**
[--Start Example(CPP 14.7.3-3): [--Start Example(CPP 14.7.3-3):
template<> class X<int> { }; // error: X not a template template<> class X<int> { }; // error: X not a template
@ -10378,6 +10443,25 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 0); parse(buffer.toString(), ParserLanguage.CPP, true, 0);
} }
/**
[--Start Example(CPP 14.7.3-11):
template<class T> class Array { };
template<class T> void sort(Array<T>& v);
// explicit specialization for sort(Array<int>&)
// with deduces templateargument of type int
template<> void sort(Array<int>&);
--End Example]
*/
public void test14_7_3s11() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { };\n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v);\n"); //$NON-NLS-1$
buffer.append("// explicit specialization for sort(Array<int>&)\n"); //$NON-NLS-1$
buffer.append("// with deduces templateargument of type int\n"); //$NON-NLS-1$
buffer.append("template<> void sort(Array<int>&);\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0 );
}
/** /**
[--Start Example(CPP 14.7.3-17): [--Start Example(CPP 14.7.3-17):
template<class T1> class A { template<class T1> class A {

View file

@ -27,6 +27,7 @@ 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.ICPPClassScope; 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.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
@ -38,7 +39,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
@ -1473,4 +1473,56 @@ public class AST2TemplateTests extends AST2BaseTest {
CR = (ICPPTemplateParameter) col.getName(14).resolveBinding(); CR = (ICPPTemplateParameter) col.getName(14).resolveBinding();
assertSame( CR, T ); assertSame( CR, T );
} }
public void testBug90689_ExplicitInstantiation() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template <class T> class Array {}; \n"); //$NON-NLS-1$
buffer.append("template <class T> void sort( Array<T> & ); \n"); //$NON-NLS-1$
buffer.append("template void sort<>( Array<int> & ); \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();
ICPPFunctionTemplate s = (ICPPFunctionTemplate) col.getName(3).resolveBinding();
ICPPClassType A2 = (ICPPClassType) col.getName(4).resolveBinding();
assertTrue( A2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A2).getTemplateDefinition(), A );
ICPPFunction s2 = (ICPPFunction) col.getName(8).resolveBinding();
assertTrue( s2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)s2).getTemplateDefinition(), s );
ICPPClassType A3 = (ICPPClassType) col.getName(10).resolveBinding();
assertTrue( A3 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A3).getTemplateDefinition(), A );
assertNotSame( A2, A3 );
}
public void test14_7_2s2_ExplicitInstantiation() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> class Array { }; \n"); //$NON-NLS-1$
buffer.append("template class Array<char>; \n"); //$NON-NLS-1$
buffer.append("template<class T> void sort(Array<T>& v) { } \n"); //$NON-NLS-1$
buffer.append("template void sort(Array<char>&); // argument is deduced here \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPClassTemplate A1 = (ICPPClassTemplate) col.getName(1).resolveBinding();
ICPPClassType A2 = (ICPPClassType) col.getName(2).resolveBinding();
assertTrue( A2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A2).getTemplateDefinition(), A1 );
ICPPFunctionTemplate s1 = (ICPPFunctionTemplate) col.getName(5).resolveBinding();
ICPPFunction s2 = (ICPPFunction) col.getName(10).resolveBinding();
assertTrue( s2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)s2).getTemplateDefinition(), s1 );
ICPPClassType A3 = (ICPPClassType) col.getName(11).resolveBinding();
assertSame( A2, A3 );
}
} }

View file

@ -42,6 +42,7 @@ 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.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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
@ -207,7 +208,11 @@ public class CPPTemplates {
parent = parent.getParent(); parent = parent.getParent();
} }
if( parent instanceof ICPPASTCompositeTypeSpecifier && segment == 1 ){ if( parent instanceof ICPPASTElaboratedTypeSpecifier && parent.getParent() instanceof IASTSimpleDeclaration
&& segment != 0 )
{
return createClassExplicitInstantiation( (ICPPASTElaboratedTypeSpecifier) parent );
} else if( parent instanceof ICPPASTCompositeTypeSpecifier && segment != 0 ){
return createClassSpecialization( (ICPPASTCompositeTypeSpecifier) parent ); return createClassSpecialization( (ICPPASTCompositeTypeSpecifier) parent );
} else if( parent instanceof ICPPASTFunctionDeclarator && segment != 0 ){ } else if( parent instanceof ICPPASTFunctionDeclarator && segment != 0 ){
return createFunctionSpecialization( id ); return createFunctionSpecialization( id );
@ -247,6 +252,25 @@ public class CPPTemplates {
return template; return template;
} }
protected static IBinding createClassExplicitInstantiation( ICPPASTElaboratedTypeSpecifier elabSpec ){
IASTName name = elabSpec.getName();
if( name instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)name).getNames();
name = ns[ ns.length - 1 ];
}
ICPPASTTemplateId id = (ICPPASTTemplateId) name;
IBinding template = id.getTemplateName().resolveBinding();
if( !(template instanceof ICPPClassTemplate) )
return null; //TODO: problem?
ICPPClassTemplate classTemplate = (ICPPClassTemplate) template;
IType [] args = createTypeArray( id.getTemplateArguments() );
if( classTemplate instanceof ICPPInternalTemplate ){
IBinding binding = ((ICPPInternalTemplate)classTemplate).instantiate( args );
return binding;
}
return null;
}
protected static IBinding createClassSpecialization( ICPPASTCompositeTypeSpecifier compSpec ){ protected static IBinding createClassSpecialization( ICPPASTCompositeTypeSpecifier compSpec ){
IASTName name = compSpec.getName(); IASTName name = compSpec.getName();
if( name instanceof ICPPASTQualifiedName ){ if( name instanceof ICPPASTQualifiedName ){
@ -321,10 +345,10 @@ public class CPPTemplates {
protected static IBinding createFunctionSpecialization( IASTName name ){ protected static IBinding createFunctionSpecialization( IASTName name ){
CPPSemantics.LookupData data = new CPPSemantics.LookupData( name ); CPPSemantics.LookupData data = new CPPSemantics.LookupData( name );
data.forceQualified = true; data.forceQualified = true;
IScope scope = CPPVisitor.getContainingScope( name ); ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope( name );
if( scope instanceof ICPPTemplateScope ){ if( scope instanceof ICPPTemplateScope ){
try { try {
scope = scope.getParent(); scope = (ICPPScope) scope.getParent();
} catch (DOMException e) { } catch (DOMException e) {
} }
} }
@ -355,18 +379,24 @@ public class CPPTemplates {
return e.getProblem(); return e.getProblem();
} }
if( map_types != null ){ if( map_types != null ){
ICPPSpecialization spec = null;
if( function instanceof ICPPMethod )
spec = new CPPMethodSpecialization( function, (ICPPScope) scope, (ObjectMap) map_types[0] );
else
spec = new CPPFunctionSpecialization( function, (ICPPScope) scope, (ObjectMap) map_types[0] );
((ICPPInternalTemplate)function).addSpecialization( (IType[]) map_types[1], spec );
while( !(parent instanceof IASTDeclaration ) ) while( !(parent instanceof IASTDeclaration ) )
parent = parent.getParent(); parent = parent.getParent();
ICPPSpecialization spec = null;
if( parent.getParent() instanceof ICPPASTExplicitTemplateInstantiation ){
spec = (ICPPSpecialization) CPPTemplates.createInstance( scope, function, (ObjectMap)map_types[0], (IType[])map_types[1] );
} else {
if( function instanceof ICPPMethod )
spec = new CPPMethodSpecialization( function, scope, (ObjectMap) map_types[0] );
else
spec = new CPPFunctionSpecialization( function, scope, (ObjectMap) map_types[0] );
if( parent instanceof IASTSimpleDeclaration ) if( parent instanceof IASTSimpleDeclaration )
((ICPPInternalBinding)spec).addDeclaration( name ); ((ICPPInternalBinding)spec).addDeclaration( name );
else if( parent instanceof IASTFunctionDefinition ) else if( parent instanceof IASTFunctionDefinition )
((ICPPInternalBinding)spec).addDefinition( name ); ((ICPPInternalBinding)spec).addDefinition( name );
}
((ICPPInternalTemplate)function).addSpecialization( (IType[]) map_types[1], spec );
return spec; return spec;
} }
//TODO problem? //TODO problem?
@ -992,6 +1022,12 @@ public class CPPTemplates {
* @return * @return
*/ */
static private IType getArgumentTypeForDeduction( IType aType, boolean pIsAReferenceType ) { static private IType getArgumentTypeForDeduction( IType aType, boolean pIsAReferenceType ) {
if( aType instanceof ICPPReferenceType ){
try {
aType = ((ICPPReferenceType)aType).getType();
} catch ( DOMException e ) {
}
}
IType result = aType; IType result = aType;
if( !pIsAReferenceType ){ if( !pIsAReferenceType ){
try { try {

View file

@ -80,6 +80,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; 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.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
@ -445,7 +446,9 @@ public class CPPVisitor {
if( parent instanceof IASTTypeId ) if( parent instanceof IASTTypeId )
return CPPSemantics.resolveBinding( name ); return CPPSemantics.resolveBinding( name );
else if( parent.getPropertyInParent() == ICPPASTTemplateSpecialization.OWNED_DECLARATION ){ else if( parent.getPropertyInParent() == ICPPASTTemplateSpecialization.OWNED_DECLARATION ||
parent.getPropertyInParent() == ICPPASTExplicitTemplateInstantiation.OWNED_DECLARATION )
{
return CPPTemplates.createFunctionSpecialization( name ); return CPPTemplates.createFunctionSpecialization( name );
} }