From b088f8e78baa77da4d02b4763ad5d540927c3447 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Mon, 18 Jul 2005 18:24:58 +0000 Subject: [PATCH] fixing bug 74276 - forward declarations of class specializations --- .../parser/tests/ast2/AST2TemplateTests.java | 100 +++++++++++------- .../core/dom/parser/cpp/CPPTemplates.java | 38 +++++-- 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 9d61c041d31..740c588f1c8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -1681,13 +1681,13 @@ public class AST2TemplateTests extends AST2BaseTest { public void testBug99254() throws Exception{ StringBuffer buffer = new StringBuffer(); - buffer.append("template class A { \n"); - buffer.append(" A( T t ); \n"); - buffer.append("}; \n"); - buffer.append("void f( A a ); \n"); - buffer.append("void m(){ \n"); - buffer.append(" f( A(1) ); \n"); - buffer.append("} \n"); + buffer.append("template class A { \n"); //$NON-NLS-1$ + buffer.append(" A( T t ); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("void f( A a ); \n"); //$NON-NLS-1$ + buffer.append("void m(){ \n"); //$NON-NLS-1$ + buffer.append(" f( A(1) ); \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); CPPNameCollector col = new CPPNameCollector(); @@ -1704,17 +1704,17 @@ public class AST2TemplateTests extends AST2BaseTest { public void testBug99254_2() throws Exception { StringBuffer buffer = new StringBuffer(); - buffer.append("namespace core { \n"); - buffer.append(" template class A { \n"); - buffer.append(" A( T x, T y ); \n"); - buffer.append(" }; \n"); - buffer.append("} \n"); - buffer.append("class B { \n"); - buffer.append(" int add(const core::A &rect ); \n"); - buffer.append("}; \n"); - buffer.append("void f( B* b ){ \n"); - buffer.append(" b->add( core::A(10, 2) ); \n"); - buffer.append("} \n"); + buffer.append("namespace core { \n"); //$NON-NLS-1$ + buffer.append(" template class A { \n"); //$NON-NLS-1$ + buffer.append(" A( T x, T y ); \n"); //$NON-NLS-1$ + buffer.append(" }; \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ + buffer.append("class B { \n"); //$NON-NLS-1$ + buffer.append(" int add(const core::A &rect ); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("void f( B* b ){ \n"); //$NON-NLS-1$ + buffer.append(" b->add( core::A(10, 2) ); \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); CPPNameCollector col = new CPPNameCollector(); @@ -1731,14 +1731,14 @@ public class AST2TemplateTests extends AST2BaseTest { public void testBug99254_3() throws Exception { StringBuffer buffer = new StringBuffer(); - buffer.append("template class A { A( T ); }; \n"); - buffer.append("typedef signed int s32; \n"); - buffer.append("class B { \n"); - buffer.append(" int add(const A &rect ); \n"); - buffer.append("}; \n"); - buffer.append("void f( B* b ){ \n"); - buffer.append(" b->add( A(10) ); \n"); - buffer.append("} \n"); + buffer.append("template class A { A( T ); }; \n"); //$NON-NLS-1$ + buffer.append("typedef signed int s32; \n"); //$NON-NLS-1$ + buffer.append("class B { \n"); //$NON-NLS-1$ + buffer.append(" int add(const A &rect ); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("void f( B* b ){ \n"); //$NON-NLS-1$ + buffer.append(" b->add( A(10) ); \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); CPPNameCollector col = new CPPNameCollector(); @@ -1754,26 +1754,26 @@ public class AST2TemplateTests extends AST2BaseTest { } public void testBug98666() throws Exception { - IASTTranslationUnit tu = parse( "A::template B b;", ParserLanguage.CPP ); + IASTTranslationUnit tu = parse( "A::template B b;", ParserLanguage.CPP ); //$NON-NLS-1$ CPPNameCollector col = new CPPNameCollector(); tu.accept( col ); ICPPASTQualifiedName qn = (ICPPASTQualifiedName) col.getName(0); IASTName [] ns = qn.getNames(); assertTrue( ns[1] instanceof ICPPASTTemplateId ); - assertEquals( ((ICPPASTTemplateId)ns[1]).toString(), "B" ); + assertEquals( ((ICPPASTTemplateId)ns[1]).toString(), "B" ); //$NON-NLS-1$ } public void testBug90678() throws Exception { StringBuffer buffer = new StringBuffer(); - buffer.append("template struct A{ \n"); - buffer.append(" class C { \n"); - buffer.append(" template struct B {}; \n"); - buffer.append(" }; \n"); - buffer.append("}; \n"); - buffer.append("template template \n"); - buffer.append("struct A::C::B{}; \n"); - buffer.append("A::C::B ab; \n"); + buffer.append("template struct A{ \n"); //$NON-NLS-1$ + buffer.append(" class C { \n"); //$NON-NLS-1$ + buffer.append(" template struct B {}; \n"); //$NON-NLS-1$ + buffer.append(" }; \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("template template \n"); //$NON-NLS-1$ + buffer.append("struct A::C::B{}; \n"); //$NON-NLS-1$ + buffer.append("A::C::B ab; \n"); //$NON-NLS-1$ IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP ); CPPNameCollector col = new CPPNameCollector(); @@ -1871,4 +1871,32 @@ public class AST2TemplateTests extends AST2BaseTest { assertEquals( bases.length, 1 ); assertSame( bases[0].getBaseClass(), B ); } + + public void testBug74276() throws Exception { + StringBuffer buffer = new StringBuffer(); + buffer.append("template < class T > class complex; \n"); //$NON-NLS-1$ + buffer.append("template <> class complex ; \n"); //$NON-NLS-1$ + buffer.append("template < class T > class complex{ \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("template <> class complex< float > { \n"); //$NON-NLS-1$ + buffer.append(" void f( float ); \n"); //$NON-NLS-1$ + buffer.append("}; \n"); //$NON-NLS-1$ + buffer.append("void complex::f(float){ \n"); //$NON-NLS-1$ + buffer.append("} \n"); //$NON-NLS-1$ + + IASTTranslationUnit tu = parse(buffer.toString(), ParserLanguage.CPP, true, true ); + CPPNameCollector col = new CPPNameCollector(); + tu.accept( col ); + + ICPPClassTemplate complex = (ICPPClassTemplate) col.getName(1).resolveBinding(); + ICPPClassType cspec = (ICPPClassType) col.getName(2).resolveBinding(); + assertTrue( cspec instanceof ICPPSpecialization ); + assertSame( ((ICPPSpecialization)cspec).getSpecializedBinding(), complex ); + + assertSame( complex, col.getName(5).resolveBinding() ); + assertSame( cspec, col.getName(6).resolveBinding() ); + + ICPPMethod f = (ICPPMethod) col.getName(8).resolveBinding(); + assertSame( f, col.getName(10).resolveBinding() ); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java index 1ece6c779de..ef1ddf750d6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java @@ -41,6 +41,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.CPPASTVisitor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +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.ICPPASTFunctionDeclarator; @@ -209,12 +210,18 @@ public class CPPTemplates { parent = parent.getParent(); } - if( parent instanceof ICPPASTElaboratedTypeSpecifier && parent.getParent() instanceof IASTSimpleDeclaration - && segment != 0 ) + IASTNode decl = parent.getParent(); + while( !(decl instanceof IASTDeclaration) ) + decl = decl.getParent(); + decl = decl.getParent(); + + if( decl instanceof ICPPASTExplicitTemplateInstantiation && + parent instanceof ICPPASTElaboratedTypeSpecifier && segment != 0 ) { return createClassExplicitInstantiation( (ICPPASTElaboratedTypeSpecifier) parent ); - } else if( parent instanceof ICPPASTCompositeTypeSpecifier && segment != 0 ){ - return createClassSpecialization( (ICPPASTCompositeTypeSpecifier) parent ); + } else if( (parent instanceof ICPPASTElaboratedTypeSpecifier || + parent instanceof ICPPASTCompositeTypeSpecifier ) && segment != 0 ){ + return createClassSpecialization( (ICPPASTDeclSpecifier) parent ); } else if( parent instanceof ICPPASTFunctionDeclarator && segment != 0 ){ return createFunctionSpecialization( id ); } @@ -272,8 +279,15 @@ public class CPPTemplates { } return null; } - protected static IBinding createClassSpecialization( ICPPASTCompositeTypeSpecifier compSpec ){ - IASTName name = compSpec.getName(); + protected static IBinding createClassSpecialization( ICPPASTDeclSpecifier compSpec ){ + IASTName name = null; + if( compSpec instanceof ICPPASTElaboratedTypeSpecifier ) + name = ((ICPPASTElaboratedTypeSpecifier)compSpec).getName(); + else if( compSpec instanceof ICPPASTCompositeTypeSpecifier ) + name = ((ICPPASTCompositeTypeSpecifier)compSpec).getName(); + else + return null; + if( name instanceof ICPPASTQualifiedName ){ IASTName [] ns = ((ICPPASTQualifiedName)name).getNames(); name = ns[ ns.length - 1 ]; @@ -304,10 +318,14 @@ public class CPPTemplates { for (int i = 0; i < templateParams.length; i++) { argMap.put( templateParams[i], args[i] ); } - - ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope( id ); - spec = new CPPClassSpecialization(binding, scope, argMap ); - ((ICPPInternalTemplate)template).addSpecialization( args, (ICPPSpecialization) spec ); + if( template instanceof ICPPInternalTemplate ){ + spec = ((ICPPInternalTemplate)template).getInstance( args ); + } + if( spec == null ) { + ICPPScope scope = (ICPPScope) CPPVisitor.getContainingScope( id ); + spec = new CPPClassSpecialization(binding, scope, argMap ); + ((ICPPInternalTemplate)template).addSpecialization( args, (ICPPSpecialization) spec ); + } IASTNode parent = id.getParent(); while( !(parent instanceof IASTDeclSpecifier ) ) parent = parent.getParent();