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):
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);
}
/**
[--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):
namespace N {
@ -10253,6 +10280,24 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
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):
char* p = 0;
@ -10268,6 +10313,26 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
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):
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);
}
/**
[--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):
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.cpp.ICPPClassScope;
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.ICPPDelegate;
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.ICPPTemplateParameter;
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.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
@ -1473,4 +1473,56 @@ public class AST2TemplateTests extends AST2BaseTest {
CR = (ICPPTemplateParameter) col.getName(14).resolveBinding();
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.ICPPASTCompositeTypeSpecifier;
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.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
@ -207,7 +208,11 @@ public class CPPTemplates {
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 );
} else if( parent instanceof ICPPASTFunctionDeclarator && segment != 0 ){
return createFunctionSpecialization( id );
@ -247,6 +252,25 @@ public class CPPTemplates {
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 ){
IASTName name = compSpec.getName();
if( name instanceof ICPPASTQualifiedName ){
@ -321,10 +345,10 @@ public class CPPTemplates {
protected static IBinding createFunctionSpecialization( IASTName name ){
CPPSemantics.LookupData data = new CPPSemantics.LookupData( name );
data.forceQualified = true;
IScope scope = CPPVisitor.getContainingScope( name );
ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope( name );
if( scope instanceof ICPPTemplateScope ){
try {
scope = scope.getParent();
scope = (ICPPScope) scope.getParent();
} catch (DOMException e) {
}
}
@ -355,19 +379,25 @@ public class CPPTemplates {
return e.getProblem();
}
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();
if( parent instanceof IASTSimpleDeclaration )
((ICPPInternalBinding)spec).addDeclaration( name );
else if( parent instanceof IASTFunctionDefinition )
((ICPPInternalBinding)spec).addDefinition( name );
return spec;
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 )
((ICPPInternalBinding)spec).addDeclaration( name );
else if( parent instanceof IASTFunctionDefinition )
((ICPPInternalBinding)spec).addDefinition( name );
}
((ICPPInternalTemplate)function).addSpecialization( (IType[]) map_types[1], spec );
return spec;
}
//TODO problem?
return null;
@ -992,6 +1022,12 @@ public class CPPTemplates {
* @return
*/
static private IType getArgumentTypeForDeduction( IType aType, boolean pIsAReferenceType ) {
if( aType instanceof ICPPReferenceType ){
try {
aType = ((ICPPReferenceType)aType).getType();
} catch ( DOMException e ) {
}
}
IType result = aType;
if( !pIsAReferenceType ){
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.ICPPASTDeclSpecifier;
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.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLiteralExpression;
@ -445,7 +446,9 @@ public class CPPVisitor {
if( parent instanceof IASTTypeId )
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 );
}