diff --git a/core/org.eclipse.cdt.core.tests/ChangeLog b/core/org.eclipse.cdt.core.tests/ChangeLog index 754234adbd3..07d25c87ddb 100644 --- a/core/org.eclipse.cdt.core.tests/ChangeLog +++ b/core/org.eclipse.cdt.core.tests/ChangeLog @@ -1,3 +1,7 @@ +2004-02-10 Andrew Niefer + Added new File: ParserSymbolTableTemplateTests.java (contains 30 new tests) + Added new File: FailingTemplateTests.java (contains 5 test stubs for failing cases) + 2004-02-10 John Camelon Added testBug47682() to QuickParseASTTests.java. diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java new file mode 100644 index 00000000000..11bfa99ab23 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/FailingTemplateTests.java @@ -0,0 +1,278 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import junit.framework.TestCase; + +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable; + +/** + * @author aniefer + */ +public class FailingTemplateTests extends TestCase { + + public ParserSymbolTable table = null; + + public FailingTemplateTests( String arg ) + { + super( arg ); + } + + public ParserSymbolTable newTable(){ + return newTable( ParserLanguage.CPP ); + } + + public ParserSymbolTable newTable( ParserLanguage language ){ + table = new ParserSymbolTable( language, ParserMode.COMPLETE_PARSE ); + return table; + } + + /** + * These tests represent code snippets from the ANSI C++ spec + */ + + + /** + * template < class T > struct A { + * void f( int ); + * template < class T2 > void f( T2 ); + * }; + * + * template <> void A::f(int) {} //non-template member + * template <> template<> void A::f<>( int ) {} //template member + * + * int main(){ + * A< char > ac; + * ac.f( 1 ); //non-template + * ac.f( 'c' ); //template + * ac.f<>(1); //template + * } + * @throws Exception + */ + public void test_14_5_2__2_MemberFunctionTemplates() throws Exception{ + + //This code snippet is misleading, the two definitions are actually + //explicit specializations for T = int, and so would not be used + //below or A< char >. This needs to be rewritten. + + +// newTable(); +// +// ITemplateSymbol templateA = table.newTemplateSymbol( "A" ); +// ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); +// templateA.addParameter( T ); +// +// table.getCompilationUnit().addSymbol( templateA ); +// +// IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); +// templateA.addSymbol( A ); +// +// IParameterizedSymbol f1 = table.newParameterizedSymbol("f", TypeInfo.t_function ); +// f1.addParameter( TypeInfo.t_int, 0, null, false ); +// f1.setIsForwardDeclaration( true ); +// A.addSymbol( f1 ); +// +// ITemplateSymbol templateF = table.newTemplateSymbol( "f" ); +// ISymbol T2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); +// +// IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); +// f2.addParameter( T2, null, false ); +// f2.setIsForwardDeclaration( true ); +// templateF.addSymbol( f2 ); +// +// A.addSymbol( templateF ); +// +// List args = new LinkedList(); +// args.add( new TypeInfo( TypeInfo.t_int,0, null ) ); +// ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", new LinkedList(), args ); +// +// LinkedList params = new LinkedList(); +// params.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); +// ISymbol look = factory.lookupMemberFunctionForDefinition( "f", params ); +// assertEquals( look, f1 ); +// +// IParameterizedSymbol f1Def = table.newParameterizedSymbol( "f", TypeInfo.t_function ); +// f1Def.addParameter( TypeInfo.t_int, 0, null, false ); +// look.setTypeSymbol( f1Def ); +// factory.addSymbol( f1Def ); +// +// factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", new LinkedList(), args ); +// assertNotNull( factory ); +// +// args.clear(); +// args.add(table.newSymbol( ParserSymbolTable.EMPTY_NAME, TypeInfo.t_int ) ); +// factory = factory.lookupTemplateForMemberDefinition( "f", new LinkedList(), new LinkedList(), args ); + } + + /** + * A specialization of a member function template does not override a virtual + * function from a base class. + * + * class B { + * virtual void f( int ); + * }; + * + * class D : public B{ + * template < class T > void f( T ); + * }; + * + * template <> void D::f< int > ( int ) {} //does not override B::f( int ); + * + * void main(){ + * D d; + * d.f( 1 ); //calls B::f( int ) + * d.f<>( 1 ); //calls D::f( int ); + * } + * @throws Exception + */ + public void test_14_5_2__4_VirtualBaseClassFunctions() throws Exception{ + //bug 51483 TBD + } + + /** + * template < class T = int > struct A { + * static int x; + * }; + * + * template <> struct A< double > {}; //specialize T == double + * template <> struct A<> {}; //specialize T == int + * + * template <> int A< char >::x = 0; + * template <> int A< float >::x = 0.5; + * + * @throws Exception + */ + public void test_14_7__3_ExplicitSpecialization() throws Exception{ + //bug 51485 + } + + /** + * Each class template specialization instantiated from a template has its own + * copy of any static members + * + * template < class T > class X { + * static T s; + * } + * + * template < class T > T X::s = 0; + * + * X a; //a.s has type int + * X b; //b.s has type char * + * @throws Exception + */ + public void test_14_7__6_ExplicitSpecializationStaticMembers() throws Exception{ + //bug 51485 + } + + /** + * template void f( void (*) (T, int) ); + * template void foo( T, int ); + * + * void g( int, int ); + * void g( char, int ); + * + * void h( int, int, int ); + * void h( char, int ); + * + * int m(){ + * f( &g ); //error, ambiguous + * f( &h ); //ok, h(char, int) is a unique match + * f( &foo ); //error, foo is a template + * } + * + * @throws Exception + */ + public void test_14_8_2_4__16_ArgumentDeduction() throws Exception{ + //This test will require resolving the address of an overloaded function + //without arguments. bug 45764 + +// newTable(); +// +// ITemplateSymbol templateF = table.newTemplateSymbol( "f" ); +// +// ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); +// templateF.addParameter( T ); +// +// IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); +// +// IParameterizedSymbol fParam = table.newParameterizedSymbol( "", TypeInfo.t_function ); +// fParam.setIsTemplateMember( true ); +// fParam.setReturnType( table.newSymbol( "", TypeInfo.t_void ) ); +// fParam.addParameter( T, null, false ); +// fParam.addParameter( TypeInfo.t_int, 0, null, false ); +// fParam.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); +// +// f.addParameter( fParam ); +// +// templateF.addSymbol( f ); +// table.getCompilationUnit().addSymbol( templateF ); +// +// ITemplateSymbol templateFoo = table.newTemplateSymbol( "foo" ); +// T = table.newSymbol( "T", TypeInfo.t_templateParameter ); +// templateFoo.addParameter( T ); +// +// IParameterizedSymbol foo = table.newParameterizedSymbol( "foo", TypeInfo.t_function ); +// foo.setReturnType( table.newSymbol( "", TypeInfo.t_void ) ); +// foo.addParameter( T, null, false ); +// foo.addParameter( TypeInfo.t_int, 0, null, false ); +// +// templateFoo.addSymbol( foo ); +// table.getCompilationUnit().addSymbol( templateFoo ); +// +// IParameterizedSymbol g1 = table.newParameterizedSymbol( "g", TypeInfo.t_function ); +// g1.addParameter( TypeInfo.t_int, 0, null, false ); +// g1.addParameter( TypeInfo.t_int, 0, null, false ); +// table.getCompilationUnit().addSymbol( g1 ); +// +// IParameterizedSymbol g2 = table.newParameterizedSymbol( "g", TypeInfo.t_function ); +// g2.addParameter( TypeInfo.t_char, 0, null, false ); +// g2.addParameter( TypeInfo.t_int, 0, null, false ); +// table.getCompilationUnit().addSymbol( g2 ); +// +// IParameterizedSymbol h1 = table.newParameterizedSymbol( "h", TypeInfo.t_function ); +// h1.addParameter( TypeInfo.t_int, 0, null, false ); +// h1.addParameter( TypeInfo.t_int, 0, null, false ); +// h1.addParameter( TypeInfo.t_int, 0, null, false ); +// table.getCompilationUnit().addSymbol( h1 ); +// +// IParameterizedSymbol h2 = table.newParameterizedSymbol( "h", TypeInfo.t_function ); +// h2.addParameter( TypeInfo.t_char, 0, null, false ); +// h2.addParameter( TypeInfo.t_int, 0, null, false ); +// table.getCompilationUnit().addSymbol( h2 ); +// +// +// +// List args = new LinkedList(); +// +// +// ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", args ); +// assertTrue( look != null ); +// assertTrue( look.isTemplateInstance() ); +// assertEquals( look.getInstantiatedSymbol(), f ); +// +// look = table.getCompilationUnit().lookup( "foo" ); +// assertTrue( look != null ); +// args.clear(); +// TypeInfo arg = new TypeInfo( TypeInfo.t_type, 0, look ); +// arg.addOperatorExpression( TypeInfo.OperatorExpression.addressof ); +// args.add( arg ); +// +// try{ +// look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", args ); +// assertTrue( false ); +// }catch ( ParserSymbolTableException e ){ +// assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateParameter ); +// } + + } +} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java new file mode 100644 index 00000000000..ad609b6a205 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTemplateTests.java @@ -0,0 +1,2193 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.core.parser.tests; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.cdt.core.parser.ParserLanguage; +import org.eclipse.cdt.core.parser.ParserMode; +import org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol; +import org.eclipse.cdt.internal.core.parser.pst.IDeferredTemplateInstance; +import org.eclipse.cdt.internal.core.parser.pst.IDerivableContainerSymbol; +import org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol; +import org.eclipse.cdt.internal.core.parser.pst.ISpecializedSymbol; +import org.eclipse.cdt.internal.core.parser.pst.ISymbol; +import org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory; +import org.eclipse.cdt.internal.core.parser.pst.ITemplateSymbol; +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable; +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableException; +import org.eclipse.cdt.internal.core.parser.pst.TypeInfo; +import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp; + +/** + * @author aniefer + */ + +public class ParserSymbolTableTemplateTests extends TestCase { + + public ParserSymbolTable table = null; + + public ParserSymbolTableTemplateTests( String arg ) + { + super( arg ); + } + + public ParserSymbolTable newTable(){ + return newTable( ParserLanguage.CPP ); + } + + public ParserSymbolTable newTable( ParserLanguage language ){ + table = new ParserSymbolTable( language, ParserMode.COMPLETE_PARSE ); + return table; + } + + /** + * + * @throws Exception + * + * template < class T > class A : public T {}; + * + * class B + * { + * int i; + * } + * + * A a; + * a.i; //finds B::i; + */ + public void testTemplateParameterAsParent() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol param = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( param ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + template.addSymbol( A ); + A.addParent( param ); + + table.getCompilationUnit().addSymbol( template ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); + ISymbol i = table.newSymbol( "i", TypeInfo.t_int ); + B.addSymbol( i ); + table.getCompilationUnit().addSymbol( B ); + + TypeInfo type = new TypeInfo( TypeInfo.t_type, 0, B ); + LinkedList args = new LinkedList(); + args.add( type ); + + IContainerSymbol instance = (IContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + assertEquals( instance.getInstantiatedSymbol(), A ); + + ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); + a.setTypeSymbol( instance ); + + table.getCompilationUnit().addSymbol( a ); + + ISymbol look = table.getCompilationUnit().lookup( "a" ); + + assertEquals( look, a ); + + ISymbol symbol = a.getTypeSymbol(); + assertEquals( symbol, instance ); + + look = instance.lookup( "i" ); + assertEquals( look, i ); + } + + /** + * + * @throws Exception + * + * template < class T > class A { T t; } + * class B : public A< int > { } + * + * B b; + * b.t; //finds A::t, will be type int + */ + public void testTemplateInstanceAsParent() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + + ISymbol param = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( param ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + template.addSymbol( A ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); + ISymbol look = template.lookup( "T" ); + assertEquals( look, param ); + t.setTypeSymbol( param ); + A.addSymbol( t ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); + table.getCompilationUnit().addSymbol( B ); + + TypeInfo type = new TypeInfo( TypeInfo.t_int, 0 , null ); + LinkedList args = new LinkedList(); + args.add( type ); + + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A ); + + B.addParent( look ); + + ISymbol b = table.newSymbol( "b", TypeInfo.t_type ); + b.setTypeSymbol( B ); + table.getCompilationUnit().addSymbol( b ); + + look = table.getCompilationUnit().lookup( "b" ); + assertEquals( look, b ); + + look = ((IDerivableContainerSymbol) b.getTypeSymbol()).lookup( "t" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), t ); + assertTrue( look.isType( TypeInfo.t_int ) ); + } + + /** + * The scope of a template-parameter extends from its point of declaration + * until the end of its template. In particular, a template parameter can be used + * in the declaration of a subsequent template-parameter and its default arguments. + * @throws Exception + * + * template< class T, class U = T > class X + * { + * T t; + * U u; + * }; + * + * X< char > x; + * x.t; + * x.u; + */ + public void testTemplateParameterDefaults() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + + ISymbol paramT = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( paramT ); + + ISymbol look = template.lookup( "T" ); + assertEquals( look, paramT ); + ISymbol paramU = table.newSymbol( "U", TypeInfo.t_templateParameter ); + paramU.getTypeInfo().setDefault( new TypeInfo( TypeInfo.t_type, 0, look ) ); + template.addTemplateParameter( paramU ); + + IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); + template.addSymbol( X ); + + look = X.lookup( "T" ); + assertEquals( look, paramT ); + ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); + t.setTypeSymbol( look ); + X.addSymbol( t ); + + look = X.lookup( "U" ); + assertEquals( look, paramU ); + ISymbol u = table.newSymbol( "u", TypeInfo.t_type ); + u.setTypeSymbol( look ); + X.addSymbol( u ); + + table.getCompilationUnit().addSymbol( template ); + + TypeInfo type = new TypeInfo( TypeInfo.t_char, 0, null ); + LinkedList args = new LinkedList(); + args.add( type ); + IDerivableContainerSymbol lookX = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "X", args ); + assertTrue( lookX.isTemplateInstance() ); + assertEquals( lookX.getInstantiatedSymbol(), X ); + + + look = lookX.lookup( "t" ); + + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), t ); + assertTrue( look.isType( TypeInfo.t_char ) ); + + look = lookX.lookup( "u" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), u ); + assertTrue( look.isType( TypeInfo.t_char ) ); + } + + /** + * + * @throws Exception + * template < class T > class A { + * T t; + * }; + * class B {}; + * void f( char c ) {} + * void f( A b ) { ... } + * void f( int i ) {} + * + * A a; + * f( a ); //calls f( A ) + * + */ + public void testTemplateParameterAsFunctionArgument() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol paramT = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( paramT ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + template.addSymbol( A ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); + t.setTypeSymbol( paramT ); + A.addSymbol( t ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); + table.getCompilationUnit().addSymbol( B ); + + LinkedList args = new LinkedList(); + TypeInfo arg = new TypeInfo( TypeInfo.t_type, 0, B ); + args.add( arg ); + + IDerivableContainerSymbol lookA = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( lookA.isTemplateInstance() ); + assertEquals( lookA.getInstantiatedSymbol(), A ); + + IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f1.addParameter( TypeInfo.t_char, 0, null, false ); + table.getCompilationUnit().addSymbol( f1 ); + + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.addParameter( lookA, null, false ); + table.getCompilationUnit().addSymbol( f2 ); + + IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.addParameter( TypeInfo.t_int, 0, null, false ); + table.getCompilationUnit().addSymbol( f3 ); + + args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, B ) ); + IDerivableContainerSymbol lookA2 = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + assertEquals( lookA2, lookA ); + + + ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); + a.setTypeSymbol( lookA ); + table.getCompilationUnit().addSymbol( a ); + + LinkedList params = new LinkedList(); + params.add( new TypeInfo( TypeInfo.t_type, 0, a ) ); + + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", params ); + assertEquals( look, f2 ); + } + + + /** + * class T { }; + * int i; + * + * template< class T, T i > void f( T t ) + * { + * T t1 = i; //template parameters T & i + * } + */ + public void test_14_1__3_ParameterLookup() throws Exception{ + newTable(); + + IDerivableContainerSymbol T = table.newDerivableContainerSymbol( "T", TypeInfo.t_class ); + table.getCompilationUnit().addSymbol( T ); + + ISymbol i = table.newSymbol( "i", TypeInfo.t_int ); + table.getCompilationUnit().addSymbol( i ); + + ITemplateSymbol template = table.newTemplateSymbol( "f" ); + + ISymbol paramT = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( paramT ); + + ISymbol parami = table.newSymbol( "i", TypeInfo.t_templateParameter ); + parami.getTypeInfo().setTemplateParameterType( TypeInfo.t_type ); + + ISymbol look = template.lookup( "T" ); + + assertEquals( look, paramT ); + parami.setTypeSymbol( look ); + template.addTemplateParameter( parami ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + ISymbol fParam = table.newSymbol( "t", TypeInfo.t_type ); + fParam.setTypeSymbol( paramT ); + f.addParameter( fParam ); + + template.addSymbol( f ); + table.getCompilationUnit().addSymbol( template ); + + look = f.lookup( "T" ); + assertEquals( look, paramT ); + + look = f.lookup( "i" ); + assertEquals( look, parami ); + } + + /** + * A non-type template parameter of type "array of T" or "function returning T" is adjusted to + * be of type "pointer to T" or "pointer to function returning T" respectively + * + * template < int *a > struct R {}; + * template < int b[5] > struct S {}; + * + * int *p; + * R

w; //ok + * S

x; //ok due to parameter adjustment + * int v[5]; + * R y; //ok due to implicit argument conversion + * S z; //ok due to adjustment and conversion + * @throws Exception + */ + public void test_14_1__8_ParameterAdjustment() throws Exception{ + newTable(); + + ITemplateSymbol templateR = table.newTemplateSymbol( "R" ); + table.getCompilationUnit().addSymbol( templateR ); + + ISymbol paramA = table.newSymbol( "a", TypeInfo.t_templateParameter ); + paramA.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + paramA.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + templateR.addTemplateParameter( paramA ); + + IDerivableContainerSymbol R = table.newDerivableContainerSymbol( "R", TypeInfo.t_struct ); + templateR.addSymbol( R ); + + ITemplateSymbol templateS = table.newTemplateSymbol( "S" ); + table.getCompilationUnit().addSymbol( templateS ); + + ISymbol paramB = table.newSymbol( "b", TypeInfo.t_templateParameter ); + paramB.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + paramB.addPtrOperator( new PtrOp( PtrOp.t_array ) ); + templateS.addTemplateParameter( paramB ); + + IDerivableContainerSymbol S = table.newDerivableContainerSymbol( "S", TypeInfo.t_struct ); + templateS.addSymbol( S ); + + ISymbol look = table.getCompilationUnit().lookup( "S" ); + assertEquals( look, templateS ); + + Iterator iter = templateS.getParameterList().iterator(); + ISymbol param = (ISymbol) iter.next(); + assertFalse( iter.hasNext() ); + iter = param.getTypeInfo().getPtrOperators().iterator(); + PtrOp ptr = (PtrOp) iter.next(); + assertFalse( iter.hasNext() ); + assertEquals( ptr.getType(), PtrOp.t_pointer ); + + ISymbol p = table.newSymbol( "p", TypeInfo.t_int ); + p.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + table.getCompilationUnit().addSymbol( p ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, p ) ); + + look = table.getCompilationUnit().lookupTemplate( "R", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), R ); + + look = table.getCompilationUnit().lookupTemplate( "S", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), S ); + + ISymbol v = table.newSymbol( "v", TypeInfo.t_int ); + v.addPtrOperator( new PtrOp( PtrOp.t_array ) ); + table.getCompilationUnit().addSymbol( v ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, v ) ); + + look = table.getCompilationUnit().lookupTemplate( "R", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), R ); + + look = table.getCompilationUnit().lookupTemplate( "S", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), S ); + } + + /** + * When default template-arguments are used, a template-argument list can be empty. In that + * case, the empty <> brackets shall still be used as the template-argument list + * + * template< class T = char > class String; + * String <> * p; //ok, T = char + * + * @throws Exception + */ + public void test_14_3__4_ParameterDefaults() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "String" ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol param = table.newSymbol( "T", TypeInfo.t_templateParameter ); + param.getTypeInfo().setDefault( new TypeInfo( TypeInfo.t_char, 0, null ) ); + template.addTemplateParameter( param ); + + IDerivableContainerSymbol string = table.newDerivableContainerSymbol( "String", TypeInfo.t_class ); + template.addSymbol( string ); + + List args = new LinkedList(); + ISymbol look = table.getCompilationUnit().lookupTemplate( "String", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), string ); + } + + /** + * A local type, a type with no linkage, an unnamed type or a type compounded from + * any of these type shall not be used as a template-argument for a template-parameter + * + * template class X { }; + * void f(){ + * struct S { }; + * + * X x; //error + * X y; //error + * } + * @throws Exception + */ + public void test_14_3_1__2_TypeArgumentRestrictions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + table.getCompilationUnit().addSymbol( template ); + + template.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + template.addSymbol( table.newDerivableContainerSymbol( "X", TypeInfo.t_class ) ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + table.getCompilationUnit().addSymbol( f ); + + IDerivableContainerSymbol S = table.newDerivableContainerSymbol( "S", TypeInfo.t_struct ); + f.addSymbol( S ); + + ISymbol look = null; + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, S ) ); + try{ + look = f.lookupTemplate( "X", args ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, S, new PtrOp( PtrOp.t_pointer ), false ) ); + try{ + look = f.lookupTemplate( "X", args ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + } + + /** + * A String literal is not an acceptable template-argument for a non-type, non-template parameter + * because a string literal is an object with internal linkage + * + * template< class T, char* p> class X {}; + * + * X< int, "Studebaker" > x1; //error + * + * char p [] = "Vivisectionist"; + * X< int, p > x2; //ok + * + * @throws Exception + */ + public void test_14_3_2__2_NonTypeArgumentRestrictions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + table.getCompilationUnit().addSymbol( template ); + + template.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + ISymbol param2 = table.newSymbol( "p", TypeInfo.t_templateParameter ); + param2.getTypeInfo().setTemplateParameterType( TypeInfo.t_char ); + param2.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + template.addTemplateParameter( param2 ); + + IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); + template.addSymbol( X ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null, new PtrOp( PtrOp.t_pointer ), "Studebaker" ) ); + + try{ + table.getCompilationUnit().lookupTemplate( "X", args ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + + ISymbol p = table.newSymbol( "p", TypeInfo.t_char ); + p.addPtrOperator( new PtrOp( PtrOp.t_array ) ); + table.getCompilationUnit().addSymbol( p ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, p ) ); + + ISymbol look = table.getCompilationUnit().lookupTemplate( "X", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), X ); + } + + /** + * names or addresses of non-static class members are not acceptable non-type template arguments + * + * template < int * p > class X {}; + * + * struct S + * { + * int m; + * static int s; + * int * t; + * } s; + * + * X<&s.m> x1; //error, address of non-static member + * X x2; //error, name of non-static member + * X<&S::s> x3; //ok, address of static member + * + * @throws Exception + */ + public void test_14_3_2__3_NonTypeArgumentRestrictions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol param = table.newSymbol( "p", TypeInfo.t_templateParameter ); + param.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + param.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + template.addTemplateParameter( param ); + + IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); + template.addSymbol( X ); + + IDerivableContainerSymbol S = table.newDerivableContainerSymbol( "S", TypeInfo.t_struct ); + table.getCompilationUnit().addSymbol( S ); + + ISymbol m = table.newSymbol( "m", TypeInfo.t_int ); + S.addSymbol( m ); + ISymbol s = table.newSymbol( "s", TypeInfo.t_int ); + s.getTypeInfo().setBit( true, TypeInfo.isStatic ); + S.addSymbol( s ); + ISymbol t = table.newSymbol( "t", TypeInfo.t_int ); + t.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + S.addSymbol( t ); + + List args = new LinkedList(); + TypeInfo arg = new TypeInfo( TypeInfo.t_type, 0, m ); + arg.addOperatorExpression( TypeInfo.OperatorExpression.addressof ); + args.add( arg ); + + try + { + table.getCompilationUnit().lookupTemplate( "X", args ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, t ) ); + + try + { + table.getCompilationUnit().lookupTemplate( "X", args ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + + args.clear(); + arg = new TypeInfo( TypeInfo.t_type, 0, s ); + arg.addOperatorExpression( TypeInfo.OperatorExpression.addressof ); + args.add( arg ); + + assertNotNull( table.getCompilationUnit().lookupTemplate( "X", args ) ); + } + + /** + * Tempories, unnamed lvalues, and named lvalues that do not have external linkage are + * not acceptable template-arguments when the corresponding template-parameter has + * reference type + * + * template< const int & I > struct B {}; + * + * B<1> b1; //error, temporary would be required + * int c = 1; + * B b2; //ok + * @throws Exception + */ + public void test_14_3_2__4_NonTypeArgumentRestrictions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "B" ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol I = table.newSymbol( "I", TypeInfo.t_templateParameter ); + I.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + I.addPtrOperator( new PtrOp( PtrOp.t_reference, true, false ) ); + template.addTemplateParameter( I ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_struct ); + template.addSymbol( B ); + + List args = new LinkedList( ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, "1" ) ); + + try{ + table.getCompilationUnit().lookupTemplate( "B", args ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateArgument ); + } + + ISymbol c = table.newSymbol( "c", TypeInfo.t_int ); + table.getCompilationUnit().addSymbol( c ); + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, c ) ); + + ISymbol look = table.getCompilationUnit().lookupTemplate( "B", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), B ); + } + + /** + * template< class T > class A { + * int x; + * }; + * + * template < class T > class A < T * > { + * long x; + * }; + * + * template< template< class U > class V > class C{ + * V< int > y; + * V< int * > z; + * } + * + * C< A > c; //V uses primary template, so C.y.x is type int + * //V uses partial specialization, so C.z.x is type long + * + * @throws Exception + */ + public void test_14_3_3__2_PartialSpecialization_TemplateTemplateParameter() throws Exception{ + newTable(); + + ITemplateSymbol templateA = table.newTemplateSymbol( "A" ); + table.getCompilationUnit().addSymbol( templateA ); + + templateA.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol A1 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + templateA.addSymbol( A1 ); + + ISymbol x1 = table.newSymbol( "x", TypeInfo.t_int ); + A1.addSymbol( x1 ); + + ISpecializedSymbol specialization = table.newSpecializedSymbol( "A" ); + templateA.addSpecialization( specialization ); + + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + specialization.addTemplateParameter( T ); + specialization.addArgument( new TypeInfo( TypeInfo.t_type, 0, T, new PtrOp( PtrOp.t_pointer ), false ) ); + + IDerivableContainerSymbol A2 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + specialization.addSymbol( A2 ); + + ISymbol x2 = table.newSymbol( "x", TypeInfo.t_int ); + x2.getTypeInfo().setBit( true, TypeInfo.isLong ); + A2.addSymbol( x2 ); + + ITemplateSymbol templateC = table.newTemplateSymbol( "C" ); + table.getCompilationUnit().addSymbol( templateC ); + + ITemplateSymbol templateV = table.newTemplateSymbol( "V" ); + templateV.setType( TypeInfo.t_templateParameter ); + templateV.getTypeInfo().setTemplateParameterType( TypeInfo.t_template ); + ISymbol U = table.newSymbol( "U", TypeInfo.t_templateParameter ); + templateV.addTemplateParameter( U ); + + templateC.addTemplateParameter( templateV ); + + IDerivableContainerSymbol C = table.newDerivableContainerSymbol( "C", TypeInfo.t_class ); + templateC.addSymbol( C ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + ISymbol look = templateC.lookupTemplate( "V", args ); + assertTrue( look != null ); + assertTrue( look instanceof IDeferredTemplateInstance ); + + ISymbol y = table.newSymbol( "y", TypeInfo.t_type ); + y.setTypeSymbol( look ); + + C.addSymbol( y ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + + look = templateC.lookupTemplate( "V", args ); + assertTrue( look != null ); + assertTrue( look instanceof IDeferredTemplateInstance ); + + ISymbol z = table.newSymbol( "z", TypeInfo.t_type ); + z.setTypeSymbol( look ); + C.addSymbol( z ); + + look = table.getCompilationUnit().lookup( "A" ); + assertEquals( look, templateA ); + + args.clear(); + args.add ( new TypeInfo( TypeInfo.t_type, 0, look ) ); + look = table.getCompilationUnit().lookupTemplate( "C", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), C ); + + IDerivableContainerSymbol lookC = (IDerivableContainerSymbol)look; + look = lookC.lookup( "y" ); + + assertEquals( look.getType(), TypeInfo.t_type ); + ISymbol symbol = look.getTypeSymbol(); + assertTrue( symbol instanceof IContainerSymbol ); + assertTrue( symbol.isTemplateInstance() ); + assertEquals( symbol.getInstantiatedSymbol(), A1 ); + + look = ((IContainerSymbol) symbol).lookup( "x" ); + + assertEquals( look.getType(), TypeInfo.t_int ); + assertEquals( look.getTypeInfo().checkBit( TypeInfo.isLong ), false ); + + look = lookC.lookup( "z" ); + assertEquals( look.getType(), TypeInfo.t_type ); + symbol = look.getTypeSymbol(); + assertTrue( symbol instanceof IContainerSymbol ); + assertTrue( symbol.isTemplateInstance() ); + assertEquals( symbol.getInstantiatedSymbol(), A2 ); + look = ((IContainerSymbol)symbol).lookup( "x" ); + + assertEquals( look.getType(), TypeInfo.t_int ); + assertEquals( look.getTypeInfo().checkBit( TypeInfo.isLong ), true ); + } + + /** + * template< class T1, class T2 > struct A { + * T1 f1(); + * void f2(); + * }; + * + * template U A< U, V >::f1() {} //ok + * + * template void A< Y, X >::f2() {} //error + * + * + * @throws Exception + */ + public void test_14_5_1__3_MemberFunctions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol primaryT1 = table.newSymbol( "T1", TypeInfo.t_templateParameter ); + ISymbol primaryT2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + template.addTemplateParameter( primaryT1 ); + template.addTemplateParameter( primaryT2 ); + + table.getCompilationUnit().addSymbol( template ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + + template.addSymbol( A ); + + IParameterizedSymbol f1 = table.newParameterizedSymbol( "f1", TypeInfo.t_function ); + f1.setIsForwardDeclaration( true ); + f1.setReturnType( primaryT1 ); + + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f2", TypeInfo.t_function ); + f2.setIsForwardDeclaration( true ); + + A.addSymbol( f1 ); + A.addSymbol( f2 ); + + ISymbol U = table.newSymbol( "U", TypeInfo.t_templateParameter ); + ISymbol V = table.newSymbol( "V", TypeInfo.t_templateParameter ); + + List params = new LinkedList(); + params.add( U ); + params.add( V ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, U ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, V ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + assertTrue( factory != null ); + IParameterizedSymbol lookF = factory.lookupMemberFunctionForDefinition( "f1", new LinkedList() ); + assertEquals( lookF, f1 ); + assertTrue( lookF.isForwardDeclaration() ); + + IParameterizedSymbol defnd = table.newParameterizedSymbol( "f1", TypeInfo.t_function ); + f1.setTypeSymbol( defnd ); + factory.addSymbol( defnd ); + + ISymbol look = defnd.lookup( "U"); + assertEquals( look, U ); + defnd.setReturnType( look ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + + IDerivableContainerSymbol lookA = (IDerivableContainerSymbol) table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( lookA.isTemplateInstance() ); + assertEquals( lookA.getInstantiatedSymbol(), A ); + + params.clear(); + look = lookA.qualifiedFunctionLookup( "f1", params ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), defnd ); + assertTrue( ((IParameterizedSymbol)look).getReturnType().isType( TypeInfo.t_int ) ); + + params.clear(); + args.clear(); + + ISymbol X = table.newSymbol( "X", TypeInfo.t_templateParameter ); + ISymbol Y = table.newSymbol( "Y", TypeInfo.t_templateParameter ); + + params.add( X ); + params.add( Y ); + + args.add( new TypeInfo( TypeInfo.t_type, 0, Y ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, X ) ); + + try{ + factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplate ); + } + } + + /** + * template struct A{ + * class B; + * }; + * template< class U > class A::B { U i; }; + * A::B b; + * + * @throws Exception + */ + public void test_14_5_1_2_MemberClass() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol primaryT = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( primaryT ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + template.addSymbol( A ); + + table.getCompilationUnit().addSymbol( template ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); + B.setIsForwardDeclaration( true ); + A.addSymbol( B ); + + List params = new LinkedList(); + ISymbol U = table.newSymbol( "U", TypeInfo.t_templateParameter ); + params.add( U ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, U ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + assertTrue( factory != null ); + + ISymbol look = factory.lookupMemberForDefinition( "B" ); + assertEquals( look, B ); + + IDerivableContainerSymbol newB = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); + look.setTypeSymbol( newB ); + + factory.addSymbol( newB ); + + ISymbol i = table.newSymbol( "i", TypeInfo.t_type ); + look = newB.lookup( "U" ); + assertEquals( look, U ); + i.setTypeSymbol( U ); + newB.addSymbol( i ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A ); + + assertTrue( look instanceof IDerivableContainerSymbol ); + IDerivableContainerSymbol lookA = (IDerivableContainerSymbol) look; + look = lookA.qualifiedLookup( "B" ); + + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), newB ); + + look = ((IDerivableContainerSymbol) look).lookup( "i" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), i ); + assertEquals( look.getType(), TypeInfo.t_int ); + } + + /** + * template< class T> class X{ + * static T s; + * }; + * + * template U X::s = 0; + * + * @throws Exception + */ + public void test_14_5_1_3_StaticDataMember() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + + table.getCompilationUnit().addSymbol( template ); + + IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); + template.addSymbol( X ); + + ISymbol s = table.newSymbol( "s", TypeInfo.t_type ); + s.setTypeSymbol( T ); + s.getTypeInfo().setBit( true, TypeInfo.isStatic ); + s.setIsForwardDeclaration( true ); + X.addSymbol( s ); + + List params = new LinkedList(); + ISymbol paramU = table.newSymbol( "U", TypeInfo.t_templateParameter ); + params.add( paramU ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, paramU ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "X", params, args ); + + assertTrue( factory != null ); + + ISymbol look = factory.lookupMemberForDefinition( "s" ); + + assertTrue( look.isForwardDeclaration() ); + + ISymbol newS = table.newSymbol( "s", TypeInfo.t_type ); + newS.setTypeSymbol( paramU ); + + look.setTypeSymbol( newS ); + + factory.addSymbol( newS ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_float, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "X", args ); + + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), X ); + + look = ((IContainerSymbol)look).qualifiedLookup( "s" ); + + assertTrue( look.isType( TypeInfo.t_float ) ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), newS ); + + } + + /** + * template< class T > class string{ + * template< class T2 > T2 compare( const T2 & ); + * }; + * + * template< class U > template< class V > V string::compare( const V & ) { + * U u; + * } + * @throws Exception + */ + public void test_14_5_2__1_MemberTemplates() throws Exception{ + newTable(); + + ITemplateSymbol template1 = table.newTemplateSymbol( "string" ); + template1.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + table.getCompilationUnit().addSymbol( template1 ); + + IDerivableContainerSymbol string = table.newDerivableContainerSymbol( "string", TypeInfo.t_class ); + template1.addSymbol( string ); + + ITemplateSymbol template2 = table.newTemplateSymbol( "compare" ); + ISymbol T2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + template2.addTemplateParameter( T2 ); + + string.addSymbol( template2 ); + + IParameterizedSymbol compare = table.newParameterizedSymbol( "compare", TypeInfo.t_function ); + compare.setIsForwardDeclaration( true ); + compare.addParameter( T2, new PtrOp( PtrOp.t_reference, true, false ), false ); + compare.setReturnType( T2 ); + template2.addSymbol( compare ); + + + List params = new LinkedList(); + ISymbol U = table.newSymbol( "U", TypeInfo.t_templateParameter ); + params.add( U ); + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, U ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "string", params, args ); + + params.clear(); + + ISymbol V = table.newSymbol( "V", TypeInfo.t_templateParameter ); + params.add( V ); + + factory = factory.lookupTemplateForMemberDefinition( "compare", params, null ); + + IParameterizedSymbol compareDef = table.newParameterizedSymbol( "compare", TypeInfo.t_function ); + ISymbol look = factory.lookupParam( "V" ); + assertEquals( look, V ); + compareDef.addParameter( look, new PtrOp( PtrOp.t_reference, true, false ), false ); + compareDef.setReturnType( look ); + compare.setTypeSymbol( compareDef ); + factory.addSymbol( compareDef ); + + look = compareDef.lookup( "U" ); + assertEquals( look, U ); + + ISymbol u = table.newSymbol( "u", TypeInfo.t_type ); + u.setTypeSymbol( look ); + + compareDef.addSymbol( u ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "string", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), string ); + + look = ((IDerivableContainerSymbol)look).lookupTemplate( "compare", args ); + assertTrue( look.isTemplateInstance() ); + assertTrue( look.getInstantiatedSymbol().isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol().getInstantiatedSymbol(), compareDef ); + + assertTrue( ((IParameterizedSymbol)look).getReturnType().isType( TypeInfo.t_int ) ); + + look = ((IContainerSymbol)look).lookup( "u" ); + assertTrue( look.isTemplateInstance() ); + assertTrue( look.getInstantiatedSymbol().isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol().getInstantiatedSymbol(), u ); + assertTrue( look.isType( TypeInfo.t_int ) ); + } + + /** + * A member function template shall not be virtual + * + * template< class T > struct A { + * template < class C > virtual void g( C ); //error + * virtual void f(); //ok + * }; + * @throws Exception + */ + public void test_14_5_2__3_VirtualMemberFunctionTemplate() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + template.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + template.addSymbol( A ); + + table.getCompilationUnit().addSymbol( template ); + + ITemplateSymbol memberTemplate = table.newTemplateSymbol( "g" ); + ISymbol C = table.newSymbol( "C", TypeInfo.t_templateParameter ); + memberTemplate.addTemplateParameter( C ); + + IParameterizedSymbol g = table.newParameterizedSymbol( "g", TypeInfo.t_function ); + g.addParameter( C, null, false ); + g.getTypeInfo().setBit( true, TypeInfo.isVirtual ); + + memberTemplate.addSymbol( g ); + + try{ + A.addSymbol( memberTemplate ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplate ); + } + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f.getTypeInfo().setBit( true, TypeInfo.isVirtual ); + + A.addSymbol( f ); + } + + /** + * Partial specialization declarations are not found by name lookup, Rather, when the primary + * template name is used, any previously declared partial template specializations of the + * primary template are also considered. + * One consequence is that a using-declaration which refers to a class template does not restrict + * the set of partial specializations which may be found through the using-declaration. + * + * namespace N{ + * template< class T1, class T2 > class A {}; + * } + * + * using N::A; + * + * namespace N{ + * template< class T> class A < T, T * > {}; + * } + * + * A< int, int * > a; //uses partial specialization + * + * @throws Exception + */ + public void test_14_5_4__7_PartialSpecializationLookup() throws Exception{ + newTable(); + + IContainerSymbol N = table.newContainerSymbol( "N", TypeInfo.t_namespace ); + + table.getCompilationUnit().addSymbol( N ); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + + template.addTemplateParameter( table.newSymbol( "T1", TypeInfo.t_templateParameter ) ); + template.addTemplateParameter( table.newSymbol( "T2", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol A1 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + + template.addSymbol( A1 ); + + N.addSymbol( template ); + + table.getCompilationUnit().addUsingDeclaration( "A", N ); + + ISpecializedSymbol spec = table.newSpecializedSymbol( "A" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + spec.addTemplateParameter( T ); + spec.addArgument( new TypeInfo( TypeInfo.t_type, 0, T ) ); + spec.addArgument( new TypeInfo( TypeInfo.t_type, 0, T, new PtrOp( PtrOp.t_pointer ), false ) ); + + IDerivableContainerSymbol A2 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + spec.addSymbol( A2 ); + template.addSpecialization( spec ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + + ISymbol look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look != null ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A2 ); + } + + /** + * + * template < class T1, class T2, int I > class A {} //#1 + * template < class T, int I > class A < T, T*, I > {} //#2 + * template < class T1, class T2, int I > class A < T1*, T2, I > {} //#3 + * template < class T > class A < int, T*, 5 > {} //#4 + * template < class T1, class T2, int I > class A < T1, T2*, I > {} //#5 + * + * A a1; //uses #1 + * A a2; //uses #2, T is int, I is 1 + * A a3; //uses #4, T is char + * A a4; //uses #5, T is int, T2 is char, I is1 + * A a5; //ambiguous, matches #3 & #5. + * + * @throws Exception + */ + public void test_14_5_4_1__2_MatchingTemplateSpecializations() throws Exception{ + newTable(); + + IDerivableContainerSymbol cls1 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + IDerivableContainerSymbol cls2 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + IDerivableContainerSymbol cls3 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + IDerivableContainerSymbol cls4 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + IDerivableContainerSymbol cls5 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + + ITemplateSymbol template1 = table.newTemplateSymbol( "A" ); + ISymbol T1p1 = table.newSymbol( "T1", TypeInfo.t_templateParameter ); + ISymbol T1p2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + ISymbol T1p3 = table.newSymbol( "I", TypeInfo.t_templateParameter ); + T1p3.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + + template1.addTemplateParameter( T1p1 ); + template1.addTemplateParameter( T1p2 ); + template1.addTemplateParameter( T1p3 ); + template1.addSymbol( cls1 ); + table.getCompilationUnit().addSymbol( template1 ); + + ISpecializedSymbol template2 = table.newSpecializedSymbol( "A" ); + ISymbol T2p1 = table.newSymbol( "T", TypeInfo.t_templateParameter ); + ISymbol T2p2 = table.newSymbol( "I", TypeInfo.t_templateParameter ); + T2p2.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + + template2.addTemplateParameter( T2p1 ); + template2.addTemplateParameter( T2p2 ); + + TypeInfo T2a1 = new TypeInfo( TypeInfo.t_type, 0, T2p1 ); + TypeInfo T2a2 = new TypeInfo( TypeInfo.t_type, 0, T2p1, new PtrOp( PtrOp.t_pointer ), false ); + TypeInfo T2a3 = new TypeInfo( TypeInfo.t_type, 0, T2p2 ); + + template2.addArgument( T2a1 ); + template2.addArgument( T2a2 ); + template2.addArgument( T2a3 ); + template2.addSymbol( cls2 ); + template1.addSpecialization( template2 ); + + ISpecializedSymbol template3 = table.newSpecializedSymbol( "A" ); + ISymbol T3p1 = table.newSymbol( "T1", TypeInfo.t_templateParameter ); + ISymbol T3p2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + ISymbol T3p3 = table.newSymbol( "I", TypeInfo.t_templateParameter ); + T3p3.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + + template3.addTemplateParameter( T3p1 ); + template3.addTemplateParameter( T3p2 ); + template3.addTemplateParameter( T3p3 ); + + TypeInfo T3a1 = new TypeInfo( TypeInfo.t_type, 0, T3p1, new PtrOp( PtrOp.t_pointer ), false ); + TypeInfo T3a2 = new TypeInfo( TypeInfo.t_type, 0, T3p2 ); + TypeInfo T3a3 = new TypeInfo( TypeInfo.t_type, 0, T3p3 ); + + template3.addArgument( T3a1 ); + template3.addArgument( T3a2 ); + template3.addArgument( T3a3 ); + template3.addSymbol( cls3 ); + template1.addSpecialization( template3 ); + + ISpecializedSymbol template4 = table.newSpecializedSymbol( "A" ); + ISymbol T4p1 = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template4.addTemplateParameter( T4p1 ); + + TypeInfo T4a1 = new TypeInfo( TypeInfo.t_int, 0, null ); + TypeInfo T4a2 = new TypeInfo( TypeInfo.t_type, 0, T4p1, new PtrOp( PtrOp.t_pointer ), false ); + TypeInfo T4a3 = new TypeInfo( TypeInfo.t_int, 0, null, null, "5" ); + //T4a3.setDefault( new Integer(5) ); + + template4.addArgument( T4a1 ); + template4.addArgument( T4a2 ); + template4.addArgument( T4a3 ); + template4.addSymbol( cls4 ); + template1.addSpecialization( template4 ); + + ISpecializedSymbol template5 = table.newSpecializedSymbol( "A" ); + ISymbol T5p1 = table.newSymbol( "T1", TypeInfo.t_templateParameter ); + ISymbol T5p2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + ISymbol T5p3 = table.newSymbol( "I", TypeInfo.t_templateParameter ); + T5p3.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + + template5.addTemplateParameter( T5p1 ); + template5.addTemplateParameter( T5p2 ); + template5.addTemplateParameter( T5p3 ); + + TypeInfo T5a1 = new TypeInfo( TypeInfo.t_type, 0, T5p1 ); + TypeInfo T5a2 = new TypeInfo( TypeInfo.t_type, 0, T5p2, new PtrOp( PtrOp.t_pointer ), false ); + TypeInfo T5a3 = new TypeInfo( TypeInfo.t_type, 0, T5p3 ); + + template5.addArgument( T5a1 ); + template5.addArgument( T5a2 ); + template5.addArgument( T5a3 ); + template5.addSymbol( cls5 ); + template1.addSpecialization( template5 ); + + ITemplateSymbol a = (ITemplateSymbol) table.getCompilationUnit().lookup( "A" ); + assertEquals( a, template1 ); + + LinkedList args = new LinkedList(); + + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(1) ) ); + + IContainerSymbol a1 = (IContainerSymbol) a.instantiate( args ); + assertTrue( a1.isTemplateInstance() ); + assertEquals( a1.getInstantiatedSymbol(), cls1 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, "1" ) ); + + IContainerSymbol a2 = (IContainerSymbol) a.instantiate( args ); + assertTrue( a2.isTemplateInstance() ); + assertEquals( a2.getInstantiatedSymbol(), cls2 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, "5" ) ); + IContainerSymbol a3 = (IContainerSymbol) a.instantiate( args ); + assertTrue( a3.isTemplateInstance() ); + assertEquals( a3.getInstantiatedSymbol(), cls4 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, "1" ) ); + IContainerSymbol a4 = (IContainerSymbol) a.instantiate( args ); + assertTrue( a4.isTemplateInstance() ); + assertEquals( a4.getInstantiatedSymbol(), cls5 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, "2" ) ); + + try{ + a.instantiate( args ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); + } + } + + /** + * template< class T > void f( T ); //#1 + * template< class T > void f( T* ); //#2 + * template< class T > void f( const T* ); //#3 + * + * const int *p; + * f( p ); //calls f( const T * ) , 3 is more specialized than 1 or 2 + * + * @throws Exception + * + */ + public void test_14_5_5_2__5_OrderingFunctionTemplates_1() throws Exception{ + newTable(); + + ITemplateSymbol template1 = table.newTemplateSymbol( "f" ); + template1.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + ISymbol T = template1.lookup( "T" ); + IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f1.addParameter( T, null, false ); + template1.addSymbol( f1 ); + table.getCompilationUnit().addSymbol( template1 ); + + ITemplateSymbol template2 = table.newTemplateSymbol( "f" ); + template2.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + T = template2.lookup( "T" ); + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.addParameter( T, new PtrOp( PtrOp.t_pointer ), false ); + template2.addSymbol( f2 ); + table.getCompilationUnit().addSymbol( template2 ); + + + ITemplateSymbol template3 = table.newTemplateSymbol( "f" ); + template3.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + T = template3.lookup( "T" ); + IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.addParameter( T, new PtrOp( PtrOp.t_pointer, true, false ), false ); + template3.addSymbol( f3 ); + table.getCompilationUnit().addSymbol( template3 ); + + ISymbol p = table.newSymbol( "p", TypeInfo.t_int ); + p.addPtrOperator( new PtrOp( PtrOp.t_pointer, true, false ) ); + table.getCompilationUnit().addSymbol( p ); + + List params = new LinkedList(); + params.add( new TypeInfo( TypeInfo.t_type, 0, p ) ); + + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", params ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f3 ); + } + + /** + * template< class T > void g( T ); //#1 + * template< class T > void g( T& ); //#2 + + * float x; + * g( x ); //ambiguous 1 or 2 + * + * @throws Exception + */ + public void test_14_5_5_2__5_OrderingFunctionTemplates_2() throws Exception{ + newTable(); + + ITemplateSymbol template1 = table.newTemplateSymbol( "g" ); + template1.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + ISymbol T = template1.lookup( "T" ); + IParameterizedSymbol g1 = table.newParameterizedSymbol( "g", TypeInfo.t_function ); + g1.addParameter( T, null, false ); + template1.addSymbol( g1 ); + table.getCompilationUnit().addSymbol( template1 ); + + ITemplateSymbol template2 = table.newTemplateSymbol( "g" ); + template2.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + T = template2.lookup( "T" ); + IParameterizedSymbol g2 = table.newParameterizedSymbol( "g", TypeInfo.t_function ); + g2.addParameter( T, new PtrOp( PtrOp.t_reference ), false ); + template2.addSymbol( g2 ); + table.getCompilationUnit().addSymbol( template2 ); + + ISymbol x = table.newSymbol( "x", TypeInfo.t_float ); + List params = new LinkedList(); + params.add( new TypeInfo( TypeInfo.t_type, 0, x ) ); + try{ + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "g", params ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); + } + } + + /** + * template< class T > struct A { }; + * + * template< class T > void h( const T & ); //#1 + * template< class T > void h( A& ); //#2 + * + * A z; + * h( z ); //calls 2 + * + * const A z2; + * h( z2 ); //calls 1 because 2 is not callable. + * @throws Exception + */ + public void test_14_5_5_2__5_OrderingFunctionTemplates_3() throws Exception{ + newTable(); + + ITemplateSymbol templateA = table.newTemplateSymbol( "A" ); + templateA.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + templateA.addSymbol( A ); + + table.getCompilationUnit().addSymbol( templateA ); + + ITemplateSymbol template1 = table.newTemplateSymbol( "h" ); + template1.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + ISymbol T = template1.lookup( "T" ); + IParameterizedSymbol h1 = table.newParameterizedSymbol( "h", TypeInfo.t_function ); + h1.addParameter( T, new PtrOp( PtrOp.t_reference, true, false ), false ); + template1.addSymbol( h1 ); + table.getCompilationUnit().addSymbol( template1 ); + + ITemplateSymbol template2 = table.newTemplateSymbol( "h" ); + template2.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + T = template2.lookup( "T" ); + + IParameterizedSymbol h2 = table.newParameterizedSymbol( "h", TypeInfo.t_function ); + List argList = new LinkedList(); + argList.add( new TypeInfo( TypeInfo.t_type, 0, T ) ); + h2.addParameter( templateA.instantiate( argList ), new PtrOp( PtrOp.t_reference ), false ); + + template2.addSymbol( h2 ); + table.getCompilationUnit().addSymbol( template2 ); + + ISymbol z = table.newSymbol( "z", TypeInfo.t_type ); + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + ISymbol look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A ); + z.setTypeSymbol( look ); + + List params = new LinkedList(); + params.add( new TypeInfo( TypeInfo.t_type, 0, z ) ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "h", params ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), h2 ); + + ISymbol z2 = table.newSymbol( "z2", TypeInfo.t_type ); + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A ); + z2.setTypeSymbol( look ); + z2.addPtrOperator( new PtrOp( PtrOp.t_undef, true, false ) ); + + params.clear(); + params.add( new TypeInfo( TypeInfo.t_type, 0, z2 ) ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "h", params ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), h1 ); + } + + /** + * Within the scope of a class template, when the name of the template is neither qualified + * nor followed by <, it is equivalent to the name of the template followed by the template-parameters + * enclosed in <>. + * + * template < class T > class X { + * X* p; //meaning X< T > + * }; + * + * @throws Exception + */ + public void test_14_6_1__1_TemplateName() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "X" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); + template.addSymbol( X ); + table.getCompilationUnit().addSymbol( template ); + + ISymbol look = X.lookup( "X" ); + + assertTrue( look != null ); + assertTrue( look instanceof IDeferredTemplateInstance ); + IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) look; + assertEquals( deferred.getTemplate(), template ); + + Iterator iter = deferred.getArguments().iterator(); + TypeInfo type = (TypeInfo) iter.next(); + assertTrue( type.isType( TypeInfo.t_type ) ); + assertEquals( type.getTypeSymbol(), T ); + } + + /** + * Within the scope of a class template specialization or partial specialization, when the name of the + * template is neither qualified nor followed by <, it is equivalent to the name of the template + * followed by the template-arguments enclosed in <> + * + * template< class T > class Y; + * + * template<> class Y< int > { + * Y* p; //meaning Y + * } + * @throws Exception + */ + public void test_14_6_1__2_SpecializationName() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "Y" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + IDerivableContainerSymbol Y1 = table.newDerivableContainerSymbol( "Y", TypeInfo.t_class ); + template.addSymbol( Y1 ); + + table.getCompilationUnit().addSymbol( template ); + + ISpecializedSymbol spec = table.newSpecializedSymbol( "Y" ); + spec.addArgument( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + template.addSpecialization( spec ); + + IDerivableContainerSymbol Y2 = table.newDerivableContainerSymbol( "Y", TypeInfo.t_class ); + spec.addSymbol( Y2 ); + + ISymbol look = Y2.lookup( "Y" ); + assertTrue( look != null ); + assertTrue( look instanceof IDeferredTemplateInstance ); + IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) look; + assertEquals( deferred.getTemplate(), spec ); + + Iterator iter = deferred.getArguments().iterator(); + TypeInfo type = (TypeInfo) iter.next(); + assertTrue( type.isType( TypeInfo.t_int ) ); + } + + /** + * A template-parameter shall not be redeclared within its scope. A template-parameter shall + * not have the same name as the template name. + * + * template< class T, int i > class Y { + * int T; //error + * void f(){ + * char T; //error + * } + * }; + * + * template class X {}; //error + * + * @throws Exception + */ + public void test_14_6_1__4_ParameterRedeclaration() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "Y" ); + template.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + ISymbol i = table.newSymbol( "i", TypeInfo.t_templateParameter ); + i.getTypeInfo().setTemplateParameterType( TypeInfo.t_int ); + + template.addTemplateParameter( i ); + + IDerivableContainerSymbol Y = table.newDerivableContainerSymbol( "Y", TypeInfo.t_class ); + template.addSymbol( Y ); + + ISymbol T = table.newSymbol( "T", TypeInfo.t_int ); + try{ + Y.addSymbol( T ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_RedeclaredTemplateParam ); + } + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + Y.addSymbol( f ); + + try{ + f.addSymbol( table.newSymbol( "T", TypeInfo.t_char ) ); + assertTrue( false ); + } catch ( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_RedeclaredTemplateParam ); + } + + ITemplateSymbol template2 = table.newTemplateSymbol( "X" ); + try{ + template2.addTemplateParameter( table.newSymbol( "X", TypeInfo.t_templateParameter ) ); + assertTrue( false ); + } catch( ParserSymbolTableException e ){ + assertEquals( e.reason, ParserSymbolTableException.r_BadTemplateParameter ); + } + } + + + + /** + * template < class T > void f( T x, T y ) { } + * struct A {}; + * struct B : A {}; + * + * A a; + * B b; + * + * f( a, b ); //error, T could be A or B + * f( b, a ); //error, T could be A or B + * f( a, a ); //ok, T is A + * f( b, b ); //ok, T is B + * @throws Exception + */ + public void test_14_8_2_4__5_ArgumentDeduction() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "f" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + + ISymbol lookT = template.lookup( "T" ); + assertEquals( lookT, T ); + + ISymbol paramX = table.newSymbol( "x", TypeInfo.t_type ); + paramX.setTypeSymbol( lookT ); + + ISymbol paramY = table.newSymbol( "y", TypeInfo.t_type ); + paramY.setTypeSymbol( lookT ); + + f.addParameter( paramX ); + f.addParameter( paramY ); + + template.addSymbol( f ); + table.getCompilationUnit().addSymbol( template ); + + IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_struct ); + table.getCompilationUnit().addSymbol( A ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_struct ); + B.addParent( A ); + table.getCompilationUnit().addSymbol( B ); + + ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); + a.setTypeSymbol( A ); + + ISymbol b = table.newSymbol( "b", TypeInfo.t_type ); + b.setTypeSymbol( B ); + + table.getCompilationUnit().addSymbol( a ); + table.getCompilationUnit().addSymbol( b ); + + List argList = new LinkedList(); + TypeInfo aParam = new TypeInfo( TypeInfo.t_type, 0, a ); + TypeInfo bParam = new TypeInfo( TypeInfo.t_type, 0, b ); + + argList.add( aParam ); + argList.add( bParam ); + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertEquals( look, null ); + + argList.clear(); + argList.add( bParam ); + argList.add( aParam ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertEquals( look, null ); + + argList.clear(); + argList.add( aParam ); + argList.add( aParam ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f ); + + argList.clear(); + argList.add( bParam ); + argList.add( bParam ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertTrue( look.isTemplateInstance()); + assertEquals( look.getInstantiatedSymbol(), f ); + } + + /** + * template< class T, class U > void f( T (*)( T, U, U ) ); + * int g1( int, float, float ); + * char g2( int, float, float ); + * int g3( int, char, float ); + * + * f( g1 ); //OK, T is int and U is float + * f( g2 ); //error, T could be char or int + * f( g3 ); //error, U could be char or float + * + * @throws Exception + */ + public void test_14_8_2_4__6_ArgumentDeduction() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "f" ); + + template.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + template.addTemplateParameter( table.newSymbol( "U", TypeInfo.t_templateParameter ) ); + + IParameterizedSymbol paramFunction = table.newParameterizedSymbol( "", TypeInfo.t_function ); + paramFunction.setIsTemplateMember( true ); + + ISymbol T = template.lookup( "T" ); + ISymbol U = template.lookup( "U" ); + + paramFunction.setReturnType( T ); + paramFunction.addParameter( T, null, false ); + paramFunction.addParameter( U, null, false ); + paramFunction.addParameter( U, null, false ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f.addParameter( paramFunction, null, false ); + + template.addSymbol( f ); + + table.getCompilationUnit().addSymbol( template ); + + IParameterizedSymbol g1 = table.newParameterizedSymbol( "g1", TypeInfo.t_function ); + g1.setReturnType( table.newSymbol( "", TypeInfo.t_int ) ); + g1.addParameter( TypeInfo.t_int, 0, null, false ); + g1.addParameter( TypeInfo.t_float, 0, null, false ); + g1.addParameter( TypeInfo.t_float, 0, null, false ); + + table.getCompilationUnit().addSymbol( g1 ); + + IParameterizedSymbol g2 = table.newParameterizedSymbol( "g2", TypeInfo.t_function ); + g2.setReturnType( table.newSymbol( "", TypeInfo.t_char ) ); + g2.addParameter( TypeInfo.t_int, 0, null, false ); + g2.addParameter( TypeInfo.t_float, 0, null, false ); + g2.addParameter( TypeInfo.t_float, 0, null, false ); + + table.getCompilationUnit().addSymbol( g2); + + IParameterizedSymbol g3 = table.newParameterizedSymbol( "g3", TypeInfo.t_function ); + g3.setReturnType( table.newSymbol( "", TypeInfo.t_int ) ); + g3.addParameter( TypeInfo.t_int, 0, null, false ); + g3.addParameter( TypeInfo.t_char, 0, null, false ); + g3.addParameter( TypeInfo.t_float, 0, null, false ); + + table.getCompilationUnit().addSymbol( g3); + + TypeInfo arg = new TypeInfo( TypeInfo.t_type, 0, g1 ); + List argList = new LinkedList(); + argList.add( arg ); + + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f ); + + arg.setTypeSymbol( g2 ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertEquals( look, null ); + + arg.setTypeSymbol( g3 ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", argList ); + assertEquals( look, null ); + } + /** + * template< class T > void f( const T * ){} + * + * int *p; + * + * f( p ); //f ( const int * ) + * + * @throws Exception + */ + public void test_14_8_2_4__7_ArgumentDeduction() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "f" ); + ISymbol T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T ); + + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f.addParameter( T, new PtrOp( PtrOp.t_pointer, true, false ), false ); + template.addSymbol( f ); + + table.getCompilationUnit().addSymbol( template ); + + ISymbol p = table.newSymbol( "p", TypeInfo.t_int ); + p.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + + List params = new LinkedList(); + params.add( new TypeInfo( TypeInfo.t_type, 0, p ) ); + ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", params ); + + assertTrue( look != null ); + assertTrue( look.isTemplateInstance() ); + + assertEquals( look.getInstantiatedSymbol(), f ); + + IParameterizedSymbol fn = (IParameterizedSymbol) look; + Iterator iter = fn.getParameterList().iterator(); + ISymbol param = (ISymbol) iter.next(); + assertTrue( param.isType( TypeInfo.t_int ) ); + + assertFalse( iter.hasNext() ); + + iter = param.getTypeInfo().getPtrOperators().iterator(); + PtrOp op = (PtrOp) iter.next(); + assertTrue( op.isConst() ); + assertEquals( op.getType(), PtrOp.t_pointer ); + assertFalse( iter.hasNext() ); + } + + /** + * template< class T > struct B {}; + * + * template< class T > struct D : public B< T > {}; + * + * struct D2 : public B< int > {}; + * + * template< class T > void f( B & ) {} + * + * D d; + * D2 d2; + * + * f( d ); //f( B & ) + * f( d2 ); //f( B & ) + * @throws Exception + */ + public void test_14_8_2_4__8_ArgumentDeduction() throws Exception{ + newTable(); + + ITemplateSymbol templateB = table.newTemplateSymbol( "B" ); + templateB.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_struct ); + templateB.addSymbol( B ); + + table.getCompilationUnit().addSymbol( templateB ); + + ITemplateSymbol templateD = table.newTemplateSymbol( "D" ); + templateD.addTemplateParameter( table.newSymbol( "T", TypeInfo.t_templateParameter ) ); + + IDerivableContainerSymbol D = table.newDerivableContainerSymbol( "D", TypeInfo.t_struct ); + templateD.addSymbol( D ); + + ISymbol T = templateD.lookup( "T" ); + List args = new LinkedList (); + args.add( new TypeInfo( TypeInfo.t_type, 0, T ) ); + ISymbol look = table.getCompilationUnit().lookupTemplate( "B", args ); + assertTrue( look instanceof IDeferredTemplateInstance ); + assertEquals( ((IDeferredTemplateInstance)look).getTemplate(), templateB ); + + D.addParent( look ); + + table.getCompilationUnit().addSymbol( templateD ); + + IDerivableContainerSymbol D2 = table.newDerivableContainerSymbol( "D2", TypeInfo.t_struct ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + look = table.getCompilationUnit().lookupTemplate( "B", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), B ); + + D2.addParent( look ); + + table.getCompilationUnit().addSymbol( D2 ); + + ITemplateSymbol templatef = table.newTemplateSymbol( "f" ); + T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + templatef.addTemplateParameter( T ); + IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, T ) ); + + look = table.getCompilationUnit().lookupTemplate( "B", args ); + assertTrue( look instanceof IDeferredTemplateInstance ); + assertEquals( ((IDeferredTemplateInstance)look).getTemplate(), templateB ); + + ISymbol param = table.newSymbol( "", TypeInfo.t_type ); + param.setTypeSymbol( look ); + param.addPtrOperator( new PtrOp( PtrOp.t_reference ) ); + f.addParameter( param ); + + templatef.addSymbol( f ); + table.getCompilationUnit().addSymbol( templatef ); + + ISymbol d = table.newSymbol( "d", TypeInfo.t_type ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + look = table.getCompilationUnit().lookupTemplate( "D", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), D ); + + d.setTypeSymbol( look ); + table.getCompilationUnit().addSymbol( d ); + + ISymbol d2 = table.newSymbol( "d2", TypeInfo.t_type ); + d2.setTypeSymbol( D2 ); + table.getCompilationUnit().addSymbol( d2 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, d ) ); + look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", args ); + assertTrue( look != null ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_type, 0, d2 ) ); + ISymbol look2 = table.getCompilationUnit().unqualifiedFunctionLookup( "f", args ); + assertTrue( look2 != null ); + assertTrue( look2.isTemplateInstance() ); + assertEquals( look2.getInstantiatedSymbol(), f ); + + //both are the template function instantiated with int, should be the same instance. + assertEquals( look, look2 ); + } + + + + + /** + * template < class T1, class T2 > class A { void f(); }; //#1 + * + * template < class T > class A < T, T > { void f(); }; //#2 + * template < class T > class A < char, T > { void f(); }; //#3 + * + * template < class U, class V > void A::f(){ + * int c; + * } + * + * template < class W > void A < W, W >::f(){ + * char c; + * } + * + * template < class X > void < char, X >::f(){ + * float c; + * } + * + * A< int, char > a1; //#1 + * A< int, int > a2; //#2 + * A< char, int > a3; //#3 + * + * a1.f(); //#1 + * a2.f(); //#2 + * a3.f(); //#3 + * + * @throws Exception + */ + public void testPartialSpecializationDefinitions() throws Exception{ + newTable(); + + ITemplateSymbol template = table.newTemplateSymbol( "A" ); + ISymbol T1 = table.newSymbol( "T1", TypeInfo.t_templateParameter ); + ISymbol T2 = table.newSymbol( "T2", TypeInfo.t_templateParameter ); + template.addTemplateParameter( T1 ); + template.addTemplateParameter( T2 ); + IDerivableContainerSymbol A1 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + template.addSymbol( A1 ); + + table.getCompilationUnit().addSymbol( template ); + + IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f1.setIsForwardDeclaration( true ); + A1.addSymbol( f1 ); + + ISpecializedSymbol spec1 = table.newSpecializedSymbol( "A" ); + ISymbol spec1_T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + + spec1.addTemplateParameter( spec1_T ); + spec1.addArgument( new TypeInfo( TypeInfo.t_type, 0, spec1_T ) ); + spec1.addArgument( new TypeInfo( TypeInfo.t_type, 0, spec1_T ) ); + + IDerivableContainerSymbol A2 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + + spec1.addSymbol( A2 ); + template.addSpecialization( spec1 ); + + IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.setIsForwardDeclaration( true ); + A2.addSymbol( f2 ); + + ISpecializedSymbol spec2 = table.newSpecializedSymbol( "A" ); + ISymbol spec2_T = table.newSymbol( "T", TypeInfo.t_templateParameter ); + + spec2.addTemplateParameter( spec2_T ); + spec2.addArgument( new TypeInfo( TypeInfo.t_char, 0, null ) ); + spec2.addArgument( new TypeInfo( TypeInfo.t_type, 0, spec2_T ) ); + + IDerivableContainerSymbol A3 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); + + spec2.addSymbol( A3 ); + template.addSpecialization( spec2 ); + + IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.setIsForwardDeclaration( true ); + A3.addSymbol( f3 ); + + ISymbol U = table.newSymbol( "U", TypeInfo.t_templateParameter ); + ISymbol V = table.newSymbol( "V", TypeInfo.t_templateParameter ); + + List params = new LinkedList(); + params.add( U ); + params.add( V ); + + List args = new LinkedList(); + args.add( new TypeInfo( TypeInfo.t_type, 0, U ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, V ) ); + + ITemplateFactory factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + + ISymbol look = factory.lookupMemberFunctionForDefinition( "f", new LinkedList() ); + assertEquals( look, f1 ); + IParameterizedSymbol f1Def = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f1.setTypeSymbol( f1Def ); + factory.addSymbol( f1Def ); + + ISymbol c1 = table.newSymbol( "c", TypeInfo.t_int ); + f1Def.addSymbol( c1 ); + + params.clear(); + args.clear(); + + ISymbol W = table.newSymbol( "W", TypeInfo.t_templateParameter ); + + params.add( W ); + args.add( new TypeInfo( TypeInfo.t_type, 0, W ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, W ) ); + + factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + + look = factory.lookupMemberFunctionForDefinition( "f", new LinkedList() ); + assertEquals( look, f2 ); + IParameterizedSymbol f2Def = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f2.setTypeSymbol( f2Def ); + factory.addSymbol( f2Def ); + + ISymbol c2 = table.newSymbol( "c", TypeInfo.t_char ); + f2Def.addSymbol( c2 ); + + params.clear(); + args.clear(); + + ISymbol X = table.newSymbol( "X", TypeInfo.t_templateParameter ); + + params.add( X ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_type, 0, X ) ); + + factory = table.getCompilationUnit().lookupTemplateForMemberDefinition( "A", params, args ); + + look = factory.lookupMemberFunctionForDefinition( "f", new LinkedList() ); + assertEquals( look, f3 ); + IParameterizedSymbol f3Def = table.newParameterizedSymbol( "f", TypeInfo.t_function ); + f3.setTypeSymbol( f3Def ); + factory.addSymbol( f3Def ); + + ISymbol c3 = table.newSymbol( "c", TypeInfo.t_float ); + f3Def.addSymbol( c3 ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A1 ); + + look = ((IContainerSymbol)look).qualifiedFunctionLookup( "f", new LinkedList() ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f1Def ); + + look = ((IContainerSymbol)look).qualifiedLookup( "c" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), c1 ); + assertTrue( look.isType( TypeInfo.t_int ) ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A2 ); + + look = ((IContainerSymbol)look).qualifiedFunctionLookup( "f", new LinkedList() ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f2Def ); + + look = ((IContainerSymbol)look).qualifiedLookup( "c" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), c2 ); + assertTrue( look.isType( TypeInfo.t_char ) ); + + args.clear(); + args.add( new TypeInfo( TypeInfo.t_char, 0, null ) ); + args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); + + look = table.getCompilationUnit().lookupTemplate( "A", args ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), A3 ); + + look = ((IContainerSymbol)look).qualifiedFunctionLookup( "f", new LinkedList() ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), f3Def ); + + look = ((IContainerSymbol)look).qualifiedLookup( "c" ); + assertTrue( look.isTemplateInstance() ); + assertEquals( look.getInstantiatedSymbol(), c3 ); + assertTrue( look.isType( TypeInfo.t_float ) ); + } +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java index 425dc92b74e..57903d84526 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java @@ -41,7 +41,6 @@ import org.eclipse.cdt.internal.core.parser.pst.IUsingDirectiveSymbol; import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable; import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTableException; import org.eclipse.cdt.internal.core.parser.pst.StandardSymbolExtension; -import org.eclipse.cdt.internal.core.parser.pst.TemplateInstance; import org.eclipse.cdt.internal.core.parser.pst.TypeFilter; import org.eclipse.cdt.internal.core.parser.pst.TypeInfo; import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.Mark; @@ -1970,391 +1969,6 @@ public class ParserSymbolTableTest extends TestCase { assertEquals( C.getUsingDirectives().size(), 0 ); } - /** - * - * @throws Exception - * - * template < class T > class A : public T {}; - * - * class B - * { - * int i; - * } - * - * A a; - * a.i; //finds B::i; - */ - public void testTemplateParameterAsParent() throws Exception{ - newTable(); - - IParameterizedSymbol template = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol param = table.newSymbol( "T", TypeInfo.t_undef ); - template.addParameter( param ); - - IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - template.addSymbol( A ); - A.addParent( param ); - - table.getCompilationUnit().addSymbol( template ); - - IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); - ISymbol i = table.newSymbol( "i", TypeInfo.t_int ); - B.addSymbol( i ); - - TypeInfo type = new TypeInfo( TypeInfo.t_class, 0, B ); - LinkedList args = new LinkedList(); - args.add( type ); - - TemplateInstance instance = table.getCompilationUnit().templateLookup( "A", args ); - assertEquals( instance.getInstantiatedSymbol(), A ); - - ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); - a.setTypeSymbol( instance ); - - table.getCompilationUnit().addSymbol( a ); - - ISymbol look = table.getCompilationUnit().lookup( "a" ); - - assertEquals( look, a ); - - ISymbol symbol = a.getTypeSymbol(); - assertEquals( symbol, instance ); - - look = ((IContainerSymbol)instance.getInstantiatedSymbol()).lookup( "i" ); - assertEquals( look, i ); - } - - /** - * - * @throws Exception - * - * template < class T > class A { T t; } - * class B : public A< int > { } - * - * B b; - * b.t; //finds A::t, will be type int - */ - public void testTemplateInstanceAsParent() throws Exception{ - newTable(); - - IParameterizedSymbol template = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol param = table.newSymbol( "T", TypeInfo.t_undef ); - template.addParameter( param ); - - IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); - - ISymbol look = template.lookup( "T" ); - assertEquals( look, param ); - - t.setTypeSymbol( param ); - - template.addSymbol( A ); - A.addSymbol( t ); - table.getCompilationUnit().addSymbol( template ); - - IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); - - TypeInfo type = new TypeInfo( TypeInfo.t_int, 0 , null ); - LinkedList args = new LinkedList(); - args.add( type ); - - look = table.getCompilationUnit().templateLookup( "A", args ); - assertTrue( look instanceof TemplateInstance ); - - B.addParent( look ); - table.getCompilationUnit().addSymbol( B ); - - ISymbol b = table.newSymbol( "b", TypeInfo.t_type ); - b.setTypeSymbol( B ); - table.getCompilationUnit().addSymbol( b ); - - look = table.getCompilationUnit().lookup( "b" ); - assertEquals( look, b ); - - look = ((IDerivableContainerSymbol) b.getTypeSymbol()).lookup( "t" ); - assertTrue( look instanceof TemplateInstance ); - - TemplateInstance instance = (TemplateInstance) look; - assertEquals( instance.getInstantiatedSymbol(), t ); - assertTrue( instance.isType( TypeInfo.t_int ) ); - - } - - /** - * The scope of a template-parameter extends from its point of declaration - * until the end of its template. In particular, a template parameter can be used - * in the declaration of a subsequent template-parameter and its default arguments. - * @throws Exception - * - * template< class T, class U = T > class X - * { - * T t; - * U u; - * }; - * - * X< char > x; - * x.t; - * x.u; - */ - public void testTemplateParameterDefaults() throws Exception{ - newTable(); - - IParameterizedSymbol template = table.newParameterizedSymbol( "X", TypeInfo.t_template ); - - ISymbol paramT = table.newSymbol( "T", TypeInfo.t_undef ); - template.addParameter( paramT ); - - ISymbol look = template.lookup( "T" ); - assertEquals( look, paramT ); - ISymbol paramU = table.newSymbol( "U", TypeInfo.t_undef ); - paramU.getTypeInfo().setDefault( new TypeInfo( TypeInfo.t_type, 0, look ) ); - template.addParameter( paramU ); - - IDerivableContainerSymbol X = table.newDerivableContainerSymbol( "X", TypeInfo.t_class ); - template.addSymbol( X ); - - look = X.lookup( "T" ); - assertEquals( look, paramT ); - ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); - t.setTypeSymbol( look ); - X.addSymbol( t ); - - look = X.lookup( "U" ); - assertEquals( look, paramU ); - ISymbol u = table.newSymbol( "u", TypeInfo.t_type ); - u.setTypeSymbol( look ); - X.addSymbol( u ); - - table.getCompilationUnit().addSymbol( template ); - - TypeInfo type = new TypeInfo( TypeInfo.t_char, 0, null ); - LinkedList args = new LinkedList(); - args.add( type ); - look = table.getCompilationUnit().templateLookup( "X", args ); - assertTrue( look instanceof TemplateInstance ); - - TemplateInstance instance = (TemplateInstance) look; - look = ((IDerivableContainerSymbol) instance.getInstantiatedSymbol()).lookup( "t" ); - - assertTrue( look instanceof TemplateInstance ); - assertTrue( ((TemplateInstance) look).isType( TypeInfo.t_char ) ); - - look = ((IDerivableContainerSymbol) instance.getInstantiatedSymbol()).lookup( "u" ); - assertTrue( look instanceof TemplateInstance ); - assertTrue( ((TemplateInstance) look).isType( TypeInfo.t_char ) ); - } - - /** - * - * @throws Exception - * template < class T > class A { - * T t; - * }; - * class B {}; - * void f( char c ) {} - * void f( A b ) { ... } - * void f( int i ) {} - * - * A a; - * f( a ); //calls f( A ) - * - */ - public void testTemplateParameterAsFunctionArgument() throws Exception{ - newTable(); - - IParameterizedSymbol template = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol paramT = table.newSymbol( "T", TypeInfo.t_undef ); - template.addParameter( paramT ); - - IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - template.addSymbol( A ); - - ISymbol t = table.newSymbol( "t", TypeInfo.t_type ); - t.setTypeSymbol( paramT ); - A.addSymbol( t ); - - table.getCompilationUnit().addSymbol( template ); - - IDerivableContainerSymbol B = table.newDerivableContainerSymbol( "B", TypeInfo.t_class ); - table.getCompilationUnit().addSymbol( B ); - - IParameterizedSymbol temp = (IParameterizedSymbol) table.getCompilationUnit().lookup( "A" ); - assertEquals( temp, template ); - - LinkedList args = new LinkedList(); - TypeInfo arg = new TypeInfo( TypeInfo.t_type, 0, B ); - args.add( arg ); - - IParameterizedSymbol f1 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); - f1.addParameter( TypeInfo.t_char, 0, null, false ); - table.getCompilationUnit().addSymbol( f1 ); - - IParameterizedSymbol f2 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); - f2.addParameter( temp.instantiate( args ), null, false ); - table.getCompilationUnit().addSymbol( f2 ); - - IParameterizedSymbol f3 = table.newParameterizedSymbol( "f", TypeInfo.t_function ); - f3.addParameter( TypeInfo.t_int, 0, null, false ); - table.getCompilationUnit().addSymbol( f3 ); - - ISymbol a = table.newSymbol( "a", TypeInfo.t_type ); - a.setTypeSymbol( temp.instantiate( args ) ); - table.getCompilationUnit().addSymbol( a ); - - LinkedList params = new LinkedList(); - params.add( new TypeInfo( TypeInfo.t_type, 0, a ) ); - - ISymbol look = table.getCompilationUnit().unqualifiedFunctionLookup( "f", params ); - assertEquals( look, f2 ); - - } - - /** - * - * template < class T1, class T2, int I > class A {} //#1 - * template < class T, int I > class A < T, T*, I > {} //#2 - * template < class T1, class T2, int I > class A < T1*, T2, I > {} //#3 - * template < class T > class A < int, T*, 5 > {} //#4 - * template < class T1, class T2, int I > class A < T1, T2*, I > {} //#5 - * - * A a1; //uses #1 - * A a2; //uses #2, T is int, I is 1 - * A a3; //uses #4, T is char - * A a4; //uses #5, T is int, T2 is char, I is1 - * A a5; //ambiguous, matches #3 & #5. - * - * @throws Exception - */ - //TODO - public void incompletetestTemplateSpecialization() throws Exception{ - newTable(); - - IDerivableContainerSymbol cls1 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - IDerivableContainerSymbol cls2 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - IDerivableContainerSymbol cls3 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - IDerivableContainerSymbol cls4 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - IDerivableContainerSymbol cls5 = table.newDerivableContainerSymbol( "A", TypeInfo.t_class ); - - IParameterizedSymbol template1 = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol T1p1 = table.newSymbol( "T1", TypeInfo.t_undef ); - ISymbol T1p2 = table.newSymbol( "T2", TypeInfo.t_undef ); - ISymbol T1p3 = table.newSymbol( "I", TypeInfo.t_int ); - template1.addParameter( T1p1 ); - template1.addParameter( T1p2 ); - template1.addParameter( T1p3 ); - template1.addSymbol( cls1 ); - table.getCompilationUnit().addSymbol( template1 ); - - IParameterizedSymbol template2 = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol T2p1 = table.newSymbol( "T", TypeInfo.t_undef ); - ISymbol T2p2 = table.newSymbol( "I", TypeInfo.t_int ); - template2.addParameter( T2p1 ); - template2.addParameter( T2p2 ); - ISymbol T2a1 = table.newSymbol( "T", TypeInfo.t_undef ); - ISymbol T2a2 = table.newSymbol( "T", TypeInfo.t_undef ); - T2a2.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); - ISymbol T2a3 = table.newSymbol( "I", TypeInfo.t_int ); - template2.addArgument( T2a1 ); - template2.addArgument( T2a2 ); - template2.addArgument( T2a3 ); - template2.addSymbol( cls2 ); - template1.addSpecialization( template2 ); - - IParameterizedSymbol template3 = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol T3p1 = table.newSymbol( "T1", TypeInfo.t_undef ); - ISymbol T3p2 = table.newSymbol( "T2", TypeInfo.t_undef ); - ISymbol T3p3 = table.newSymbol( "I", TypeInfo.t_int ); - template3.addParameter( T3p1 ); - template3.addParameter( T3p2 ); - template3.addParameter( T3p3 ); - ISymbol T3a1 = table.newSymbol( "T1", TypeInfo.t_undef ); - T3a1.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); - ISymbol T3a2 = table.newSymbol( "T2", TypeInfo.t_undef ); - ISymbol T3a3 = table.newSymbol( "I", TypeInfo.t_int ); - template3.addArgument( T3a1 ); - template3.addArgument( T3a2 ); - template3.addArgument( T3a3 ); - template3.addSymbol( cls3 ); - template1.addSpecialization( template3 ); - - IParameterizedSymbol template4 = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol T4p1 = table.newSymbol( "T", TypeInfo.t_undef ); - template4.addParameter( T4p1 ); - - ISymbol T4a1 = table.newSymbol( "", TypeInfo.t_int ); - ISymbol T4a2 = table.newSymbol( "T", TypeInfo.t_undef ); - T4a2.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); - ISymbol T4a3 = table.newSymbol( "", TypeInfo.t_int ); - T4a3.getTypeInfo().setDefault( new Integer(5) ); - template4.addArgument( T4a1 ); - template4.addArgument( T4a2 ); - template4.addArgument( T4a3 ); - template4.addSymbol( cls4 ); - template1.addSpecialization( template4 ); - - IParameterizedSymbol template5 = table.newParameterizedSymbol( "A", TypeInfo.t_template ); - ISymbol T5p1 = table.newSymbol( "T1", TypeInfo.t_undef ); - ISymbol T5p2 = table.newSymbol( "T2", TypeInfo.t_undef ); - ISymbol T5p3 = table.newSymbol( "I", TypeInfo.t_int ); - template5.addParameter( T5p1 ); - template5.addParameter( T5p2 ); - template5.addParameter( T5p3 ); - ISymbol T5a1 = table.newSymbol( "T1", TypeInfo.t_undef ); - ISymbol T5a2 = table.newSymbol( "T2", TypeInfo.t_undef ); - T5a1.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); - ISymbol T5a3 = table.newSymbol( "I", TypeInfo.t_int ); - template5.addArgument( T5a1 ); - template5.addArgument( T5a2 ); - template5.addArgument( T5a3 ); - template5.addSymbol( cls5 ); - template1.addSpecialization( template5 ); - - IParameterizedSymbol a = (IParameterizedSymbol) table.getCompilationUnit().lookup( "A" ); - - LinkedList args = new LinkedList(); - - args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(1) ) ); - - TemplateInstance a1 = a.instantiate( args ); - assertEquals( a1.getInstantiatedSymbol(), cls1 ); - - args.clear(); - args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(1) ) ); - - TemplateInstance a2 = a.instantiate( args ); - assertEquals( a2.getInstantiatedSymbol(), cls2 ); - - args.clear(); - args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); - args.add( new TypeInfo( TypeInfo.t_char, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(5) ) ); - TemplateInstance a3 = a.instantiate( args ); - assertEquals( a3.getInstantiatedSymbol(), cls4 ); - - args.clear(); - args.add( new TypeInfo( TypeInfo.t_int, 0, null ) ); - args.add( new TypeInfo( TypeInfo.t_char, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(1) ) ); - TemplateInstance a4 = a.instantiate( args ); - assertEquals( a4.getInstantiatedSymbol(), cls5 ); - - args.clear(); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, new PtrOp( PtrOp.t_pointer ), false ) ); - args.add( new TypeInfo( TypeInfo.t_int, 0, null, null, new Integer(2) ) ); - - try{ - a.instantiate( args ); - } catch ( ParserSymbolTableException e ){ - assertEquals( e.reason, ParserSymbolTableException.r_Ambiguous ); - } - } - /** * class A; * diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java index 8c3a47bdd92..3bb605aa7ea 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ParserTestSuite.java @@ -30,6 +30,7 @@ public class ParserTestSuite extends TestCase { suite.addTestSuite(ExprEvalTest.class); suite.addTestSuite(QuickParseASTTests.class); suite.addTestSuite(ParserSymbolTableTest.class); + suite.addTestSuite(ParserSymbolTableTemplateTests.class ); suite.addTestSuite(CModelElementsTests.class); suite.addTestSuite(CompletionParseTest.class); // suite.addTestSuite(MacroTests.class); diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog-parser b/core/org.eclipse.cdt.core/parser/ChangeLog-parser index 585ff5bc069..a800c7612ec 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog-parser +++ b/core/org.eclipse.cdt.core/parser/ChangeLog-parser @@ -1,6 +1,17 @@ 2004-02-10 John Camelon Workaround for Bug 51502 - Parser spins on particular file (Scalability) +2004-02-10 Andrew Niefer + Templates in the symbol table (org.eclipse.cdt.internal.core.parser.pst) + ITemplateFactory.java + ITemplateSymbol.java + DeferredTemplateInstance.java + ParserSymbolTableError.java + TemplateEngine.java + TemplateFactory.java + TemplateSymbol.java + Most of the other main symbol table files (BasicSymbol, ContainerSymbol, etc) were modified + 2004-02-10 John Camelon Fixed Bug 51302 - Content Assist: No completion list available following namespace declaration. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicSymbol.java index 00521aecc7e..3689abd6a70 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/BasicSymbol.java @@ -1,8 +1,15 @@ +/********************************************************************** + * Copyright (c) 2003, 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ /* * Created on Nov 4, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments */ package org.eclipse.cdt.internal.core.parser.pst; @@ -54,6 +61,17 @@ public class BasicSymbol implements Cloneable, ISymbol return copy; } + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( !isTemplateMember() && !getContainingSymbol().isTemplateMember() ){ + return null; + } + ISymbol newSymbol = (ISymbol) clone(); + newSymbol.setTypeInfo( TemplateEngine.instantiateTypeInfo( newSymbol.getTypeInfo(), template, argMap ) ); + newSymbol.setInstantiatedSymbol( this ); + + return newSymbol; + } + public String getName() { return _name; } public void setName(String name) { _name = name; } @@ -160,14 +178,14 @@ public class BasicSymbol implements Cloneable, ISymbol public void setIsTemplateMember( boolean isMember ){ _isTemplateMember = isMember; } - public ISymbol getTemplateInstance(){ - return _templateInstance; + public boolean isTemplateInstance(){ + return ( _instantiatedSymbol != null ); } - public void setTemplateInstance( TemplateInstance instance ){ - _templateInstance = instance; + public ISymbol getInstantiatedSymbol(){ + return _instantiatedSymbol; } - public Map getArgumentMap(){ - return null; + public void setInstantiatedSymbol( ISymbol symbol ){ + _instantiatedSymbol = symbol; } public boolean getIsInvisible(){ @@ -183,7 +201,8 @@ public class BasicSymbol implements Cloneable, ISymbol private IContainerSymbol _containingScope; //the scope that contains us private int _depth; //how far down the scope stack we are - private boolean _isInvisible = false; //used by friend declarations (11.4-9) - private boolean _isTemplateMember = false; - private TemplateInstance _templateInstance; + private boolean _isInvisible = false; //used by friend declarations (11.4-9) + + private boolean _isTemplateMember = false; + private ISymbol _instantiatedSymbol = null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java index ca60717cfe1..359ee806bc6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ContainerSymbol.java @@ -60,10 +60,77 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { copy._containedSymbols = ( _containedSymbols != null )? (Map)((TreeMap) _containedSymbols).clone() : null; else copy._containedSymbols = ( _containedSymbols != null )? (Map)((HashMap) _containedSymbols).clone() : null; - + + copy._contents = ( _contents != null )? (LinkedList) _contents.clone() : null; + return copy; } + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( !isTemplateMember() || template == null ){ + return null; + } + + ContainerSymbol newContainer = (ContainerSymbol) super.instantiate( template, argMap ); + + Iterator iter = getContentsIterator(); + + newContainer.getContainedSymbols().clear(); + if( newContainer._contents != null ){ + newContainer._contents.clear(); + + IExtensibleSymbol containedSymbol = null; + ISymbol newSymbol = null; + + while( iter.hasNext() ){ + containedSymbol = (IExtensibleSymbol) iter.next(); + + if( containedSymbol instanceof IUsingDirectiveSymbol ){ + newContainer._contents.add( containedSymbol ); + } else { + ISymbol symbol = (ISymbol) containedSymbol; + if( symbol.isForwardDeclaration() && symbol.getTypeSymbol() != null ){ + continue; + } + + Map instanceMap = argMap; + if( template.getDefinitionParameterMap() != null && + template.getDefinitionParameterMap().containsKey( containedSymbol ) ) + { + Map defMap = (Map) template.getDefinitionParameterMap().get( containedSymbol ); + instanceMap = new HashMap(); + Iterator i = defMap.keySet().iterator(); + while( i.hasNext() ){ + ISymbol p = (ISymbol) i.next(); + instanceMap.put( p, argMap.get( defMap.get( p ) ) ); + } + } + + newSymbol = ((ISymbol)containedSymbol).instantiate( template, instanceMap ); + + newSymbol.setContainingSymbol( newContainer ); + newContainer._contents.add( newSymbol ); + + if( newContainer.getContainedSymbols().containsKey( newSymbol.getName() ) ){ + Object obj = newContainer.getContainedSymbols().get( newSymbol.getName() ); + if( obj instanceof List ){ + ((List) obj).add( obj ); + } else { + List list = new LinkedList(); + list.add( obj ); + list.add( newSymbol ); + newContainer.getContainedSymbols().put( newSymbol.getName(), list ); + } + } else { + newContainer.getContainedSymbols().put( newSymbol.getName(), newSymbol ); + } + } + } + } + + return newContainer; + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#addSymbol(org.eclipse.cdt.internal.core.parser.pst.ISymbol) */ @@ -83,13 +150,16 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } } - //Templates contain 1 declaration - if( getType() == TypeInfo.t_template ){ - //declaration must be a class or a function - if( ( obj.getType() != TypeInfo.t_class && obj.getType() != TypeInfo.t_function ) || - ( getContainedSymbols() != null && getContainedSymbols().size() == 1 ) ) - { - //throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); + if( obj.isType( TypeInfo.t_template ) ){ + if( ! TemplateEngine.canAddTemplate( containing, (ITemplateSymbol) obj ) ) { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); + } + } + + //14.6.1-4 A Template parameter shall not be redeclared within its scope. + if( isTemplateMember() || isType( TypeInfo.t_template ) ){ + if( TemplateEngine.alreadyHasTemplateParameter( this, obj.getName() ) ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_RedeclaredTemplateParam ); } } @@ -114,7 +184,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } else if( origObj.getClass() == LinkedList.class ){ origList = (LinkedList)origObj; } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); } boolean validOverride = ((origList == null) ? ParserSymbolTable.isValidOverload( origDecl, obj ) : ParserSymbolTable.isValidOverload( origList, obj ) ); @@ -220,11 +290,10 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#addUsingDeclaration(java.lang.String, org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol) */ public ISymbol addUsingDeclaration( String name, IContainerSymbol declContext ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_any, null ); + LookupData data = new LookupData( name, TypeInfo.t_any ); if( declContext != null ){ data.qualified = true; - data.templateInstance = declContext.getTemplateInstance(); ParserSymbolTable.lookup( data, declContext ); } else { ParserSymbolTable.lookup( data, this ); @@ -291,22 +360,34 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#elaboratedLookup(org.eclipse.cdt.internal.core.parser.pst.TypeInfo.eType, java.lang.String) */ public ISymbol elaboratedLookup( TypeInfo.eType type, String name ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, type, getTemplateInstance() ); + LookupData data = new LookupData( name, type ); ParserSymbolTable.lookup( data, this ); - return ParserSymbolTable.resolveAmbiguities( data ); + ISymbol found = ParserSymbolTable.resolveAmbiguities( data ); + + if( isTemplateMember() && found instanceof ITemplateSymbol ) { + return TemplateEngine.instantiateWithinTemplateScope( this, (ITemplateSymbol) found ); + } + + return found; } /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#lookup(java.lang.String) */ public ISymbol lookup( String name ) throws ParserSymbolTableException { - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_any ); ParserSymbolTable.lookup( data, this ); - return ParserSymbolTable.resolveAmbiguities( data ); + ISymbol found = ParserSymbolTable.resolveAmbiguities( data ); + + if( isTemplateMember() && found instanceof ITemplateSymbol ) { + return TemplateEngine.instantiateWithinTemplateScope( this, (ITemplateSymbol) found ); + } + + return found; } /* (non-Javadoc) @@ -341,7 +422,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * for a definition. */ public ISymbol lookupMemberForDefinition( String name ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_any ); data.qualified = true; IContainerSymbol container = this; @@ -360,7 +441,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } public IParameterizedSymbol lookupMethodForDefinition( String name, List parameters ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_any ); data.qualified = true; data.parameters = ( parameters == null ) ? new LinkedList() : parameters; @@ -398,7 +479,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { private IContainerSymbol lookupNestedNameSpecifier(String name, IContainerSymbol inSymbol ) throws ParserSymbolTableException{ ISymbol foundSymbol = null; - LookupData data = new LookupData( name, TypeInfo.t_namespace, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_namespace ); data.filter.addAcceptedType( TypeInfo.t_class ); data.filter.addAcceptedType( TypeInfo.t_struct ); data.filter.addAcceptedType( TypeInfo.t_union ); @@ -406,7 +487,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { data.foundItems = ParserSymbolTable.lookupInContained( data, inSymbol ); if( data.foundItems != null ){ - foundSymbol = ParserSymbolTable.resolveAmbiguities( data );//, data.foundItems ); + foundSymbol = ParserSymbolTable.resolveAmbiguities( data ); } if( foundSymbol == null && inSymbol.getContainingSymbol() != null ){ @@ -431,7 +512,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#qualifiedLookup(java.lang.String, org.eclipse.cdt.internal.core.parser.pst.TypeInfo.eType) */ public ISymbol qualifiedLookup( String name, TypeInfo.eType t ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, t, getTemplateInstance() ); + LookupData data = new LookupData( name, t ); data.qualified = true; ParserSymbolTable.lookup( data, this ); @@ -496,7 +577,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { } } - LookupData data = new LookupData( name, TypeInfo.t_function, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_function ); //if parameters == null, thats no parameters, but we need to distinguish that from //no parameter information at all, so make an empty list. data.parameters = ( parameters == null ) ? new LinkedList() : parameters; @@ -554,7 +635,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * include argument dependant scopes */ public IParameterizedSymbol memberFunctionLookup( String name, List parameters ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_function, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_function ); //if parameters == null, thats no parameters, but we need to distinguish that from //no parameter information at all, so make an empty list. data.parameters = ( parameters == null ) ? new LinkedList() : parameters; @@ -567,7 +648,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#qualifiedFunctionLookup(java.lang.String, java.util.List) */ public IParameterizedSymbol qualifiedFunctionLookup( String name, List parameters ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_function, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_function ); data.qualified = true; //if parameters == null, thats no parameters, but we need to distinguish that from //no parameter information at all, so make an empty list. @@ -581,21 +662,42 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#templateLookup(java.lang.String, java.util.List) */ - public TemplateInstance templateLookup( String name, List arguments ) throws ParserSymbolTableException + public ISymbol lookupTemplate( String name, List arguments ) throws ParserSymbolTableException { - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); - data.parameters = arguments; + LookupData data = new LookupData( name, TypeInfo.t_any ); ParserSymbolTable.lookup( data, this ); ISymbol found = ParserSymbolTable.resolveAmbiguities( data ); - if( found.isType( TypeInfo.t_template ) ){ - return ((IParameterizedSymbol) found).instantiate( arguments ); + + if( (found.isType( TypeInfo.t_templateParameter ) && found.getTypeInfo().getTemplateParameterType() == TypeInfo.t_template) || + found.isType( TypeInfo.t_template ) ) + { + return ((ITemplateSymbol) found).instantiate( arguments ); + } else if( found.getContainingSymbol().isType( TypeInfo.t_template ) ){ + return ((ITemplateSymbol) found.getContainingSymbol()).instantiate( arguments ); } + return null; } + public ITemplateFactory lookupTemplateForMemberDefinition( String name, List parameters, List arguments ) throws ParserSymbolTableException{ + LookupData data = new LookupData( name, TypeInfo.t_any ); + + ParserSymbolTable.lookup( data, this ); + ISymbol look = ParserSymbolTable.resolveAmbiguities( data ); + + if( look instanceof ITemplateSymbol ){ + ITemplateSymbol template = TemplateEngine.selectTemplateOrSpecialization( (ITemplateSymbol) look, parameters, arguments ); + if( template != null ){ + return new TemplateFactory( template, parameters ); + } + } + return null; + } + + public List prefixLookup( TypeFilter filter, String prefix, boolean qualified ) throws ParserSymbolTableException{ - LookupData data = new LookupData( prefix, filter, getTemplateInstance() ); + LookupData data = new LookupData( prefix, filter ); data.qualified = qualified; data.mode = ParserSymbolTable.LookupMode.PREFIX; @@ -640,11 +742,9 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { if( node instanceof IASTMember ){ ASTAccessVisibility visibility; - try { - visibility = ParserSymbolTable.getVisibility( symbol, qualifyingSymbol ); - } catch (ParserSymbolTableException e) { - return false; - } + + visibility = ParserSymbolTable.getVisibility( symbol, qualifyingSymbol ); + if( visibility == ASTAccessVisibility.PUBLIC ){ return true; } @@ -704,61 +804,6 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol { return false; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#instantiate(java.util.List) - */ - public TemplateInstance instantiate( List arguments ) throws ParserSymbolTableException{ - if( getType() != TypeInfo.t_template ){ - return null; - } - - //TODO uncomment when template specialization matching & ordering is working - //IParameterizedSymbol template = ParserSymbolTable.matchTemplatePartialSpecialization( this, arguments ); - IParameterizedSymbol template = null; - - if( template == null ){ - template = (IParameterizedSymbol) this; - } - - List paramList = template.getParameterList(); - int numParams = ( paramList != null ) ? paramList.size() : 0; - - if( numParams == 0 ){ - return null; - } - - HashMap map = new HashMap(); - Iterator paramIter = paramList.iterator(); - Iterator argIter = arguments.iterator(); - - ISymbol param = null; - TypeInfo arg = null; - for( int i = 0; i < numParams; i++ ){ - param = (ISymbol) paramIter.next(); - - if( argIter.hasNext() ){ - arg = (TypeInfo) argIter.next(); - map.put( param, arg ); - } else { - Object obj = param.getTypeInfo().getDefault(); - if( obj != null && obj instanceof TypeInfo ){ - map.put( param, obj ); - } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); - } - } - } - - if( template.getContainedSymbols().size() != 1 ){ - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); - } - - Iterator iter = template.getContainedSymbols().keySet().iterator(); - IContainerSymbol symbol = (IContainerSymbol) template.getContainedSymbols().get( iter.next() ); - - TemplateInstance instance = new TemplateInstance( getSymbolTable(), symbol, map ); - return instance; - } protected List getContents(){ if(_contents == null ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DeferredTemplateInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DeferredTemplateInstance.java new file mode 100644 index 00000000000..67b880aa4ed --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DeferredTemplateInstance.java @@ -0,0 +1,74 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +/** + * @author aniefer + * + * To change the template for this generated type comment go to + * Window - Preferences - Java - Code Generation - Code and Comments + */ +public class DeferredTemplateInstance extends BasicSymbol implements IDeferredTemplateInstance { + + public DeferredTemplateInstance( ParserSymbolTable table, ITemplateSymbol template, List args ){ + super(table, ParserSymbolTable.EMPTY_NAME ); + _template = template; + _arguments = new LinkedList( args ); + + setContainingSymbol( template ); + } + + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IDeferredTemplateInstance#getTemplate() + */ + public ITemplateSymbol getTemplate() { + return _template; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IDeferredTemplateInstance#getArgumentMap() + */ + public List getArguments() { + return _arguments; + } + + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + List args = getArguments(); + List newArgs = new LinkedList(); + Iterator iter = args.iterator(); + + while( iter.hasNext() ){ + TypeInfo arg = (TypeInfo) iter.next(); + newArgs.add( TemplateEngine.instantiateTypeInfo( arg, template, argMap ) ); + } + + ITemplateSymbol deferredTemplate = getTemplate(); + if( deferredTemplate.isType( TypeInfo.t_templateParameter ) && argMap.containsKey( deferredTemplate ) ){ + TypeInfo i = (TypeInfo) argMap.get( deferredTemplate ); + deferredTemplate = (ITemplateSymbol) i.getTypeSymbol(); + } + + ISymbol instance = deferredTemplate.instantiate( newArgs ); +// if( !( instance instanceof IDeferredTemplateInstance ) ) +// return instance.instantiate( template, argMap ); +// else + return instance; + } + + private ITemplateSymbol _template; + private List _arguments; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java index f83f51777bc..43febbce569 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/DerivableContainerSymbol.java @@ -54,6 +54,44 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva return copy; } + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( !isTemplateMember() ){ + return null; + } + + DerivableContainerSymbol newSymbol = (DerivableContainerSymbol) super.instantiate( template, argMap ); + + Iterator parents = getParents().iterator(); + + newSymbol.getParents().clear(); + ParentWrapper wrapper = null, newWrapper = null; + while( parents.hasNext() ){ + wrapper = (ParentWrapper) parents.next(); + newWrapper = new ParentWrapper( wrapper.getParent(), wrapper.isVirtual(), wrapper.getAccess(), wrapper.getOffset(), wrapper.getReferences() ); + ISymbol parent = newWrapper.getParent(); + if( parent instanceof IDeferredTemplateInstance ){ + newWrapper.setParent( ((IDeferredTemplateInstance)parent).instantiate( template, argMap ) ); + } else if( parent.isType( TypeInfo.t_templateParameter ) && argMap.containsKey( parent ) ){ + TypeInfo info = (TypeInfo) argMap.get( parent ); + newWrapper.setParent( info.getTypeSymbol() ); + } + + newSymbol.getParents().add( newWrapper ); + } + + Iterator constructors = getConstructors().iterator(); + newSymbol.getConstructors().clear(); + IParameterizedSymbol constructor = null; + while( constructors.hasNext() ){ + constructor = (IParameterizedSymbol) constructors.next(); + newSymbol.getConstructors().add( constructor.instantiate( template, argMap ) ); + } + + //TODO: friends + + return newSymbol; + } + public void addSymbol(ISymbol symbol) throws ParserSymbolTableException { super.addSymbol( symbol ); @@ -149,7 +187,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva */ public IParameterizedSymbol lookupConstructor( List parameters ) throws ParserSymbolTableException { - LookupData data = new LookupData( ParserSymbolTable.EMPTY_NAME, TypeInfo.t_constructor, null ); + LookupData data = new LookupData( ParserSymbolTable.EMPTY_NAME, TypeInfo.t_constructor ); data.parameters = parameters; List constructors = new LinkedList(); @@ -194,7 +232,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva //of function will have them from the original declaration boolean foundThis = false; - LookupData data = new LookupData( ParserSymbolTable.THIS, TypeInfo.t_any, null ); + LookupData data = new LookupData( ParserSymbolTable.THIS, TypeInfo.t_any ); try { Map map = ParserSymbolTable.lookupInContained( data, obj ); foundThis = map.containsKey( data.name ); @@ -274,7 +312,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva * class scope. */ public ISymbol lookupForFriendship( String name ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_any ); IContainerSymbol enclosing = getContainingSymbol(); if( enclosing != null && enclosing.isType( TypeInfo.t_namespace, TypeInfo.t_union ) ){ @@ -290,7 +328,7 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva } public IParameterizedSymbol lookupFunctionForFriendship( String name, List parameters ) throws ParserSymbolTableException{ - LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() ); + LookupData data = new LookupData( name, TypeInfo.t_any ); data.parameters = parameters; @@ -373,6 +411,15 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva this.references = r; } + public Object clone(){ + try{ + return super.clone(); + } catch ( CloneNotSupportedException e ){ + //should not happen + return null; + } + } + public void setParent( ISymbol parent ){ this.parent = parent; } public ISymbol getParent() { return parent; } @@ -380,7 +427,6 @@ public class DerivableContainerSymbol extends ContainerSymbol implements IDeriva public void setVirtual( boolean virtual ){ isVirtual = virtual; } - public ASTAccessVisibility getVisibility(){ return access; } public ASTAccessVisibility getAccess() { return access; } public int getOffset() { return offset; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java index 887950dcc1b..cd657f115cc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IContainerSymbol.java @@ -10,9 +10,6 @@ ******************************************************************************/ /* * Created on May 9, 2003 - * - * To change the template for this generated file go to - * Window>Preferences>Java>Code Generation>Code and Comments */ package org.eclipse.cdt.internal.core.parser.pst; @@ -52,8 +49,11 @@ public interface IContainerSymbol extends ISymbol { public IParameterizedSymbol unqualifiedFunctionLookup( String name, List parameters ) throws ParserSymbolTableException; public IParameterizedSymbol memberFunctionLookup( String name, List parameters ) throws ParserSymbolTableException; public IParameterizedSymbol qualifiedFunctionLookup( String name, List parameters ) throws ParserSymbolTableException; - public TemplateInstance templateLookup( String name, List arguments ) throws ParserSymbolTableException; - public TemplateInstance instantiate( List arguments ) throws ParserSymbolTableException; + + public ISymbol lookupTemplate( String name, List arguments ) throws ParserSymbolTableException; + + public ITemplateFactory lookupTemplateForMemberDefinition( String name, List templateParameters, + List templateArguments ) throws ParserSymbolTableException; public boolean isVisible( ISymbol symbol, IContainerSymbol qualifyingSymbol ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDeferredTemplateInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDeferredTemplateInstance.java new file mode 100644 index 00000000000..883c7a8b182 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDeferredTemplateInstance.java @@ -0,0 +1,24 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.List; + +/** + * @author aniefer + */ + +public interface IDeferredTemplateInstance extends ISymbol { + + public ITemplateSymbol getTemplate(); + + public List getArguments(); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java index 985acc6bd73..1e8e14304b8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IDerivableContainerSymbol.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -44,13 +44,13 @@ public interface IDerivableContainerSymbol extends IContainerSymbol { public List getFriends(); - public interface IParentSymbol{ + public interface IParentSymbol extends Cloneable { + public Object clone(); public void setParent( ISymbol parent ); public ISymbol getParent(); public boolean isVirtual(); public void setVirtual( boolean virtual ); - public ASTAccessVisibility getVisibility(); public ASTAccessVisibility getAccess(); public int getOffset(); public List getReferences(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java index 4dd4ca86c74..3d04d75af63 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/IParameterizedSymbol.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -32,10 +32,6 @@ public interface IParameterizedSymbol extends IContainerSymbol { public void addParameter( TypeInfo.eType type, int info, TypeInfo.PtrOp ptrOp, boolean hasDefault ); public void addParameter( ISymbol typeSymbol, TypeInfo.PtrOp ptrOp, boolean hasDefault ); - public void addArgument( ISymbol arg ); - public List getArgumentList(); - //public void setArgumentList( List list ); - public Map getParameterMap(); public List getParameterList(); //public void setParameterList( List list ); @@ -47,8 +43,4 @@ public interface IParameterizedSymbol extends IContainerSymbol { public void setHasVariableArgs( boolean var ); public boolean hasVariableArgs( ); - - public boolean hasSpecializations(); - public void addSpecialization( IParameterizedSymbol spec ); - public List getSpecializations(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISpecializedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISpecializedSymbol.java index cf44c75eb69..0f50b3bd5a0 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISpecializedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISpecializedSymbol.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003,2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -16,12 +16,21 @@ */ package org.eclipse.cdt.internal.core.parser.pst; +import java.util.List; + /** * @author aniefer * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ -public interface ISpecializedSymbol extends IParameterizedSymbol { +public interface ISpecializedSymbol extends ITemplateSymbol { + + public void addArgument( TypeInfo arg ); + + public List getArgumentList(); + + public ITemplateSymbol getPrimaryTemplate(); + public void setPrimaryTemplate( ITemplateSymbol templateSymbol ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISymbol.java index a1fdc73cd71..f62e27c4a02 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ISymbol.java @@ -21,6 +21,8 @@ public interface ISymbol extends Cloneable, IExtensibleSymbol { public Object clone(); + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException; + public void setName(String name); public String getName(); @@ -43,12 +45,12 @@ public interface ISymbol extends Cloneable, IExtensibleSymbol { public List getPtrOperators(); public void addPtrOperator( TypeInfo.PtrOp ptrOp ); + public boolean isTemplateInstance(); + public ISymbol getInstantiatedSymbol(); + public void setInstantiatedSymbol( ISymbol symbol ); public boolean isTemplateMember(); public void setIsTemplateMember( boolean isMember ); - public ISymbol getTemplateInstance(); - public Map getArgumentMap(); - public void setTemplateInstance( TemplateInstance instance ); - + public int getDepth(); public boolean getIsInvisible(); public void setIsInvisible( boolean invisible ); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateFactory.java new file mode 100644 index 00000000000..e57cfa0f675 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateFactory.java @@ -0,0 +1,31 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.List; + +/** + * @author aniefer + **/ + +public interface ITemplateFactory { + + public void addSymbol( ISymbol symbol ) throws ParserSymbolTableException; + + public ISymbol lookupMemberForDefinition( String name ) throws ParserSymbolTableException; + public IParameterizedSymbol lookupMemberFunctionForDefinition( String name, List params ) throws ParserSymbolTableException; + + public ITemplateFactory lookupTemplateForMemberDefinition( String name, List templateParameters, + List templateArguments ) throws ParserSymbolTableException; + public ITemplateSymbol getPrimaryTemplate(); + + public ISymbol lookupParam( String name ) throws ParserSymbolTableException; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java new file mode 100644 index 00000000000..63433b35601 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ITemplateSymbol.java @@ -0,0 +1,40 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.List; +import java.util.Map; + +/** + * @author aniefer + */ + +public interface ITemplateSymbol extends IParameterizedSymbol { + + public void addTemplateParameter( ISymbol param ) throws ParserSymbolTableException; + + public boolean hasSpecializations(); + public void addSpecialization( ISpecializedSymbol spec ); + public List getSpecializations(); + + public IContainerSymbol getTemplatedSymbol(); + + public Map getDefinitionParameterMap(); + + public ISpecializedSymbol findSpecialization(List parameters, List arguments); + public IContainerSymbol findInstantiation( List arguments ); + public List findArgumentsFor( IContainerSymbol instance ); + + public void addInstantiation( IContainerSymbol instance, List args ); + public ISymbol instantiate( List args ) throws ParserSymbolTableException; + public IDeferredTemplateInstance deferredInstance( List args ); + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java index ebc04793cbf..411f1175f08 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParameterizedSymbol.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -53,12 +53,48 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz else copy._parameterMap = ( _parameterMap != null ) ? (Map) ((HashMap) _parameterMap).clone() : null; - copy._argumentList = ( _argumentList != null ) ? (LinkedList) _argumentList.clone() : null; - copy._specializations = ( _specializations != null ) ? (LinkedList) _specializations.clone() : null; - return copy; } + public ISymbol instantiate( ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( !isTemplateMember() ){ + return null; + } + + ParameterizedSymbol newParameterized = (ParameterizedSymbol) super.instantiate( template, argMap ); + + if( _returnType != null ){ + if( _returnType.isType( TypeInfo.t_templateParameter ) ){ + if( argMap.containsKey( _returnType ) ){ + newParameterized.setReturnType( getSymbolTable().newSymbol( ParserSymbolTable.EMPTY_NAME ) ); + newParameterized.getReturnType().setTypeInfo( (TypeInfo) argMap.get( _returnType ) ); + newParameterized.getReturnType().setInstantiatedSymbol( _returnType ); + } + } else { + newParameterized.setReturnType( _returnType.instantiate( template, argMap ) ); + } + } + + Iterator iter = getParameterList().iterator(); + + newParameterized.getParameterList().clear(); + newParameterized.getParameterMap().clear(); + + ISymbol param = null, newParam = null; + + while( iter.hasNext() ){ + param = (ISymbol) iter.next(); + newParam = param.instantiate( template, argMap ); + + newParameterized.getParameterList().add( newParam ); + if( !newParam.getName().equals( ParserSymbolTable.EMPTY_NAME ) ){ + newParameterized.getParameterMap().put( newParam.getName(), newParam ); + } + } + + return newParameterized; + } + /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addParameter(org.eclipse.cdt.internal.core.parser.pst.ISymbol) */ @@ -113,36 +149,6 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz addParameter( param ); } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addArgument(org.eclipse.cdt.internal.core.parser.pst.ISymbol) - */ - public void addArgument( ISymbol arg ){ - List argumentList = getArgumentList(); - argumentList.add( arg ); - - arg.setIsTemplateMember( isTemplateMember() || getType() == TypeInfo.t_template ); - - Command command = new AddArgumentCommand( this, arg ); - getSymbolTable().pushCommand( command ); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getArgumentList() - */ - public List getArgumentList(){ - if( _argumentList == null ){ - _argumentList = new LinkedList(); - } - return _argumentList; - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#setArgumentList(java.util.List) - */ -// public void setArgumentList( List list ){ -// _argumentList = new LinkedList( list ); -// } - /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getParameterMap() */ @@ -222,33 +228,6 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz return _returnType; } - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#hasSpecializations() - */ - public boolean hasSpecializations(){ - return ( _specializations != null && !_specializations.isEmpty() ); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addSpecialization(org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol) - */ - public void addSpecialization( IParameterizedSymbol spec ){ - List specializationList = getSpecializations(); - specializationList.add( spec ); - - spec.setContainingSymbol( getContainingSymbol() ); - } - - /* (non-Javadoc) - * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getSpecializations() - */ - public List getSpecializations() { - if( _specializations == null ){ - _specializations = new LinkedList(); - } - return _specializations; - } - public void setHasVariableArgs( boolean var ){ _hasVarArgs = var; } @@ -277,23 +256,9 @@ public class ParameterizedSymbol extends ContainerSymbol implements IParameteriz private ISymbol _param; } - static private class AddArgumentCommand extends Command{ - public AddArgumentCommand( IParameterizedSymbol container, ISymbol arg ){ - _decl = container; - _arg = arg; - } - public void undoIt(){ - _decl.getArgumentList().remove( _arg ); - } - - private IParameterizedSymbol _decl; - private ISymbol _arg; - } private LinkedList _parameterList; //have my cake private Map _parameterMap; //and eat it too - private LinkedList _specializations; //template specializations - private LinkedList _argumentList; //template specialization arguments private ISymbol _returnType; private boolean _hasVarArgs = false; //whether or not this function has variable arguments } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java index 6264c9ae74f..d2a9bb03c91 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java @@ -82,6 +82,10 @@ public class ParserSymbolTable { public IParameterizedSymbol newParameterizedSymbol( String name, TypeInfo.eType type ){ return new ParameterizedSymbol( this, name, type ); } + public ITemplateSymbol newTemplateSymbol( String name ){ + return new TemplateSymbol( this, name ); + } + public ISpecializedSymbol newSpecializedSymbol( String name ){ return new SpecializedSymbol( this, name ); } @@ -309,7 +313,7 @@ public class ParserSymbolTable { if( declarations instanceof SortedMap ){ iterator = ((SortedMap)declarations).tailMap( data.name.toLowerCase() ).keySet().iterator(); } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); } } @@ -339,41 +343,83 @@ public class ParserSymbolTable { } if( lookIn instanceof IParameterizedSymbol ){ - Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap(); - if( parameters != null ){ - iterator = null; - if( data.mode == LookupMode.PREFIX ){ - if( parameters instanceof SortedMap ){ - iterator = ((SortedMap) parameters).tailMap( data.name.toLowerCase() ).keySet().iterator(); - } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); - } - } - name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name; - while( name != null ){ - if( nameMatches( data, name ) ){ - obj = parameters.get( name ); - obj = collectSymbol( data, obj ); - if( obj != null ){ - found.put( name, obj ); - } - } else { - break; - } - - if( iterator != null && iterator.hasNext() ){ - name = (String) iterator.next(); - } else { - name = null; - } - } - - } + lookupInParameters(data, lookIn, found); } + if( lookIn.isTemplateMember() && data.templateMember == null ){ + IContainerSymbol containing = lookIn.getContainingSymbol(); + IContainerSymbol outer = (containing != null ) ? containing.getContainingSymbol() : null; + if( ( containing instanceof IDerivableContainerSymbol && outer instanceof ITemplateSymbol) || + ( lookIn instanceof IParameterizedSymbol && containing instanceof ITemplateSymbol ) ) + { + data.templateMember = lookIn; + } + } + return found; + } - + /** + * @param data + * @param lookIn + * @param found + * @throws ParserSymbolTableException + */ + private static void lookupInParameters(LookupData data, IContainerSymbol lookIn, Map found) throws ParserSymbolTableException { + Object obj; + Iterator iterator; + String name; + + if( lookIn instanceof ITemplateSymbol && ((ITemplateSymbol)lookIn).getDefinitionParameterMap() != null ){ + ITemplateSymbol template = (ITemplateSymbol) lookIn; + if( data.templateMember != null && template.getDefinitionParameterMap().containsKey( data.templateMember ) ){ + Map map = (Map) template.getDefinitionParameterMap().get( data.templateMember ); + iterator = map.keySet().iterator(); + while( iterator.hasNext() ){ + ISymbol symbol = (ISymbol) iterator.next(); + if( nameMatches( data, symbol.getName() ) ){ + obj = collectSymbol( data, symbol ); + if( obj != null ){ + found.put( symbol.getName(), obj ); + } + } + } + return; + } + + } + Map parameters = ((IParameterizedSymbol)lookIn).getParameterMap(); + if( parameters != null ){ + iterator = null; + if( data.mode == LookupMode.PREFIX ){ + if( parameters instanceof SortedMap ){ + iterator = ((SortedMap) parameters).tailMap( data.name.toLowerCase() ).keySet().iterator(); + } else { + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); + } + } + + name = ( iterator != null && iterator.hasNext() ) ? (String) iterator.next() : data.name; + while( name != null ){ + if( nameMatches( data, name ) ){ + obj = parameters.get( name ); + obj = collectSymbol( data, obj ); + if( obj != null ){ + found.put( name, obj ); + } + } else { + break; + } + + if( iterator != null && iterator.hasNext() ){ + name = (String) iterator.next(); + } else { + name = null; + } + } + } + } + private static boolean nameMatches( LookupData data, String name ){ if( data.mode == LookupMode.PREFIX ){ return name.regionMatches( true, 0, data.name, 0, data.name.length() ); @@ -386,15 +432,6 @@ public class ParserSymbolTable { return true; } - if( data.templateInstance != null && symbol.isTemplateMember() ){ - if( symbol.isType( TypeInfo.t_type ) ){ - symbol = symbol.getTypeSymbol(); - } - if( symbol.isType( TypeInfo.t_undef ) && symbol.getContainingSymbol().isType( TypeInfo.t_template ) ){ - TypeInfo info = (TypeInfo) data.templateInstance.getArgumentMap().get( symbol ); - return data.filter.shouldAccept( symbol, info ); - } - } return data.filter.shouldAccept( symbol ); } @@ -409,22 +446,30 @@ public class ParserSymbolTable { ISymbol symbol = ( iter != null ) ? (ISymbol) iter.next() : (ISymbol) object; Set functionSet = new HashSet(); + Set templateFunctionSet = new HashSet(); + ISymbol obj = null; IContainerSymbol cls = null; while( symbol != null ){ + if( symbol instanceof ITemplateSymbol ){ + ISymbol temp = ((ITemplateSymbol)symbol).getTemplatedSymbol(); + symbol = ( temp != null ) ? temp : symbol; + } + if( !symbol.getIsInvisible() && checkType( data, symbol ) ){//, data.type, data.upperType ) ){ - if( symbol.isTemplateMember() && data.templateInstance != null ) - foundSymbol = new TemplateInstance( symbol.getSymbolTable(), symbol, data.templateInstance.getArgumentMap() ); - else - foundSymbol = symbol; + foundSymbol = symbol; if( foundSymbol.isType( TypeInfo.t_function ) ){ if( foundSymbol.isForwardDeclaration() && foundSymbol.getTypeSymbol() != null ){ foundSymbol = foundSymbol.getTypeSymbol(); } + if( foundSymbol.getContainingSymbol().isType( TypeInfo.t_template ) ){ + templateFunctionSet.add( foundSymbol ); + } else { + functionSet.add( foundSymbol ); + } - functionSet.add( foundSymbol ); } else { //if this is a class-name, other stuff hides it if( foundSymbol.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){ @@ -473,6 +518,7 @@ public class ParserSymbolTable { } int numFunctions = functionSet.size(); + int numTemplateFunctions = templateFunctionSet.size(); boolean ambiguous = false; @@ -481,9 +527,23 @@ public class ParserSymbolTable { if( obj != null && cls.getContainingSymbol() != obj.getContainingSymbol()){ ambiguous = true; } + + Iterator fnIter = null; + IParameterizedSymbol fn = null; + if( !templateFunctionSet.isEmpty() ){ + fnIter = templateFunctionSet.iterator(); + + for( int i = numTemplateFunctions; i > 0; i-- ){ + fn = (IParameterizedSymbol) fnIter.next(); + if( cls.getContainingSymbol()!= fn.getContainingSymbol()){ + ambiguous = true; + break; + } + } + } if( !functionSet.isEmpty() ){ - Iterator fnIter = functionSet.iterator(); - IParameterizedSymbol fn = null; + fnIter = functionSet.iterator(); + for( int i = numFunctions; i > 0; i-- ){ fn = (IParameterizedSymbol) fnIter.next(); if( cls.getContainingSymbol()!= fn.getContainingSymbol()){ @@ -494,6 +554,17 @@ public class ParserSymbolTable { } } + if( numTemplateFunctions > 0 ){ + if( data.parameters != null ){ + List fns = TemplateEngine.selectTemplateFunctions( templateFunctionSet, data.parameters ); + functionSet.addAll( fns ); + numFunctions = functionSet.size(); + } else { + functionSet.addAll( templateFunctionSet ); + numFunctions += numTemplateFunctions; + } + } + if( obj != null && !ambiguous ){ if( numFunctions > 0 ){ ambiguous = true; @@ -526,13 +597,11 @@ public class ParserSymbolTable { */ private static Map lookupInParents( LookupData data, ISymbol lookIn ) throws ParserSymbolTableException{ IDerivableContainerSymbol container = null; - /*if( lookIn instanceof TemplateInstance ){ - - } else*/ + if( lookIn instanceof IDerivableContainerSymbol ){ container = (IDerivableContainerSymbol) lookIn; } else{ - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); } List scopes = container.getParents(); @@ -561,14 +630,7 @@ public class ParserSymbolTable { { wrapper = (IDerivableContainerSymbol.IParentSymbol) iterator.next(); ISymbol parent = wrapper.getParent(); - if( parent.isType( TypeInfo.t_undef ) && parent.getContainingSymbol().isType( TypeInfo.t_template ) ){ - TypeInfo info = (TypeInfo) data.templateInstance.getArgumentMap().get( parent ); - if( info.getTypeSymbol() instanceof IDerivableContainerSymbol ){ - parent = (IDerivableContainerSymbol) info.getTypeSymbol(); - } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); - } - } + if( !wrapper.isVirtual() || !data.visited.contains( parent ) ){ if( wrapper.isVirtual() ){ data.visited.add( parent ); @@ -578,16 +640,7 @@ public class ParserSymbolTable { //is circular inheritance if( ! data.inheritanceChain.contains( parent ) ){ //is this name define in this scope? - if( parent instanceof TemplateInstance ){ - ISymbol tempInstance = data.templateInstance; - data.templateInstance = (TemplateInstance) parent; - ISymbol instance = ((TemplateInstance)parent).getInstantiatedSymbol(); - if( instance instanceof IContainerSymbol ) - temp = lookupInContained( data, (IContainerSymbol)instance ); - else - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); - data.templateInstance = tempInstance; - } else if( parent instanceof IDerivableContainerSymbol ){ + if( parent instanceof IDerivableContainerSymbol ){ temp = lookupInContained( data, (IDerivableContainerSymbol) parent ); } else { throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo ); @@ -707,6 +760,24 @@ public class ParserSymbolTable { TypeInfo.eType origType = origSymbol.getType(); TypeInfo.eType newType = newSymbol.getType(); + if( origType == TypeInfo.t_template ){ + ITemplateSymbol template = (ITemplateSymbol) origSymbol; + origSymbol = (ISymbol) template.getContainedSymbols().get( template.getName() ); + if( origSymbol == null ) + return true; + else + origType = origSymbol.getType(); + } + + if( newType == TypeInfo.t_template ){ + ITemplateSymbol template = (ITemplateSymbol) newSymbol; + newSymbol = (ISymbol) template.getContainedSymbols().get( template.getName() ); + if( newSymbol == null ) + return true; + else + newType = newSymbol.getType(); + } + //handle forward decls if( origSymbol.getTypeInfo().isForwardDeclaration() ){ if( origSymbol.getTypeSymbol() == newSymbol ) @@ -736,7 +807,11 @@ public class ParserSymbolTable { if( origList.size() == 1 ){ return isValidOverload( (ISymbol)origList.iterator().next(), newSymbol ); } else if ( origList.size() > 1 ){ - + if( newSymbol.isType( TypeInfo.t_template ) ){ + ITemplateSymbol template = (ITemplateSymbol) newSymbol; + newSymbol = (ISymbol) template.getContainedSymbols().get( template.getName() ); + } + //the first thing can be a class-name or enumeration name, but the rest //must be functions. So make sure the newDecl is a function before even //considering the list @@ -746,13 +821,20 @@ public class ParserSymbolTable { Iterator iter = origList.iterator(); ISymbol symbol = (ISymbol) iter.next(); - boolean valid = isValidOverload( symbol, newSymbol );//( (symbol.getType().compareTo( TypeInfo.t_class ) >= 0 ) && (symbol.getType().compareTo( TypeInfo.t_enumeration ) <= 0 ) ); + + if( symbol.isType( TypeInfo.t_template ) ){ + IParameterizedSymbol template = (IParameterizedSymbol) symbol; + symbol = (ISymbol) template.getContainedSymbols().get( template.getName() ); + } - if( !valid && (symbol instanceof IParameterizedSymbol) ) - valid = isValidFunctionOverload( (IParameterizedSymbol)symbol, (IParameterizedSymbol)newSymbol ); + boolean valid = isValidOverload( symbol, newSymbol ); while( valid && iter.hasNext() ){ symbol = (ISymbol) iter.next(); + if( symbol.isType( TypeInfo.t_template ) ){ + IParameterizedSymbol template = (IParameterizedSymbol) symbol; + symbol = (ISymbol) template.getContainedSymbols().get( template.getName() ); + } valid = ( symbol instanceof IParameterizedSymbol) && isValidFunctionOverload( (IParameterizedSymbol)symbol, (IParameterizedSymbol)newSymbol ); } @@ -829,6 +911,11 @@ public class ParserSymbolTable { if( symbol.isType( TypeInfo.t_function ) ){ functionList.add( symbol ); } else { + if( symbol.isTemplateMember() && !symbol.isTemplateInstance() && + !symbol.isType( TypeInfo.t_templateParameter ) && symbol.getContainingSymbol().isType( TypeInfo.t_template )) + { + return symbol.getContainingSymbol(); + } return symbol; } } @@ -1010,6 +1097,17 @@ public class ParserSymbolTable { ambiguous |= ( hasWorse && hasBetter ) || ( !hasWorse && !hasBetter ); if( !hasWorse ){ + if( !hasBetter ){ + //if they are both template functions, we can order them that way + if( bestFn.isTemplateInstance() && currFn.isTemplateInstance() ){ + ITemplateSymbol t1 = (ITemplateSymbol) bestFn.getInstantiatedSymbol().getContainingSymbol(); + ITemplateSymbol t2 = (ITemplateSymbol) currFn.getInstantiatedSymbol().getContainingSymbol(); + int order = TemplateEngine.orderTemplateFunctions( t1, t2 ); + if ( order < 0 ){ + hasBetter = true; + } + } + } if( hasBetter ){ //the new best function. ambiguous = false; @@ -1177,16 +1275,8 @@ public class ParserSymbolTable { return 0; } IDerivableContainerSymbol symbol = null; - TemplateInstance instance = null; - if( obj instanceof TemplateInstance ){ - instance = (TemplateInstance) obj; - ISymbol temp = instance.getInstantiatedSymbol(); - if( temp instanceof IDerivableContainerSymbol ){ - symbol = (IDerivableContainerSymbol) temp; - } else { - return -1; - } - } else if( obj instanceof IDerivableContainerSymbol ){ + + if( obj instanceof IDerivableContainerSymbol ){ symbol = (IDerivableContainerSymbol) obj; } else { return -1; @@ -1203,48 +1293,23 @@ public class ParserSymbolTable { for( int i = size; i > 0; i-- ){ wrapper = (IDerivableContainerSymbol.IParentSymbol) iter.next(); temp = wrapper.getParent(); - boolean isVisible = ( wrapper.getVisibility() == ASTAccessVisibility.PUBLIC ); - if( temp instanceof TemplateInstance ){ - instance = (TemplateInstance) temp; - if( instance.getInstantiatedSymbol() instanceof IDerivableContainerSymbol ){ - if( instance.getInstantiatedSymbol() == base ){ - if( throwIfNotVisible && !isVisible ) - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadVisibility ); - else - return 1; - } else { - int n = hasBaseClass( instance, base, throwIfNotVisible ); - if( n > 0 ){ - return n + 1; - } - } - } + boolean isVisible = ( wrapper.getAccess() == ASTAccessVisibility.PUBLIC ); + if ( temp instanceof IDerivableContainerSymbol ){ + parent = (IDerivableContainerSymbol)temp; } else { - if( temp.isType( TypeInfo.t_undef ) && temp.getContainingSymbol().isType( TypeInfo.t_template ) ){ - if( instance == null ) continue; - TypeInfo info = (TypeInfo) instance.getArgumentMap().get( temp ); - if( info == null || !info.isType( TypeInfo.t_class, TypeInfo.t_struct ) ){ - continue; - } - parent = (IDerivableContainerSymbol) info.getTypeSymbol(); - } - else if ( temp instanceof IDerivableContainerSymbol ){ - parent = (IDerivableContainerSymbol)temp; - } else { - continue; - } - if( parent == base ){ - if( throwIfNotVisible && !isVisible ) - throw new ParserSymbolTableException( ParserSymbolTableException.r_BadVisibility ); - else - return 1; - } else { - int n = hasBaseClass( parent, base, throwIfNotVisible ); - if( n > 0 ){ - return n + 1; - } - } + continue; } + if( parent == base ){ + if( throwIfNotVisible && !isVisible ) + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadVisibility ); + else + return 1; + } else { + int n = hasBaseClass( parent, base, throwIfNotVisible ); + if( n > 0 ){ + return n + 1; + } + } } } @@ -1285,13 +1350,17 @@ public class ParserSymbolTable { for( int i = size; i > 0; i-- ){ wrapper = (IDerivableContainerSymbol.IParentSymbol) iter.next(); - base = wrapper.getParent(); - classes.add( base ); - if( base.getContainingSymbol().getType() == TypeInfo.t_namespace ){ - classes.add( base.getContainingSymbol()); + base = wrapper.getParent(); + //TODO: what about IDeferredTemplateInstance parents? + if( base instanceof IDerivableContainerSymbol ){ + classes.add( base ); + if( base.getContainingSymbol().getType() == TypeInfo.t_namespace ){ + classes.add( base.getContainingSymbol()); + } + + getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) base, classes ); } - getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) base, classes ); } } } @@ -1637,7 +1706,7 @@ public class ParserSymbolTable { } } - static private Cost checkStandardConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException{ + static protected Cost checkStandardConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException{ Cost cost = lvalue_to_rvalue( source, target ); if( cost.source == null || cost.target == null ){ @@ -1699,18 +1768,13 @@ public class ParserSymbolTable { if( target.getType() == TypeInfo.t_type ){ targetDecl = target.getTypeSymbol(); if( targetDecl.isType( TypeInfo.t_class, TypeInfo.t_union ) ){ - LookupData data = new LookupData( EMPTY_NAME, TypeInfo.t_constructor, null ); + LookupData data = new LookupData( EMPTY_NAME, TypeInfo.t_constructor); data.parameters = new LinkedList(); data.parameters.add( source ); data.forUserDefinedConversion = true; IDerivableContainerSymbol container = (IDerivableContainerSymbol) targetDecl; - if( targetDecl instanceof TemplateInstance ){ - data.templateInstance = targetDecl; - container = (IDerivableContainerSymbol)((TemplateInstance) targetDecl).getInstantiatedSymbol(); - } - if( !container.getConstructors().isEmpty() ){ LinkedList constructors = new LinkedList( container.getConstructors() ); constructor = resolveFunction( data, constructors ); @@ -1731,7 +1795,7 @@ public class ParserSymbolTable { String name = target.toString(); if( !name.equals(EMPTY_NAME) ){ - LookupData data = new LookupData( "operator " + name, TypeInfo.t_function, null ); //$NON-NLS-1$ + LookupData data = new LookupData( "operator " + name, TypeInfo.t_function ); //$NON-NLS-1$ LinkedList params = new LinkedList(); data.parameters = params; data.forUserDefinedConversion = true; @@ -1853,7 +1917,7 @@ public class ParserSymbolTable { info = typeSymbol.getTypeInfo(); } - if( info.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){ + if( info.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) || info.isType( TypeInfo.t_function ) ){ returnInfo.setType( TypeInfo.t_type ); returnInfo.setTypeSymbol( typeSymbol ); } else { @@ -1868,7 +1932,7 @@ public class ParserSymbolTable { if( topInfo.hasPtrOperators() ){ TypeInfo.PtrOp topPtr = (PtrOp) topInfo.getPtrOperators().iterator().next(); TypeInfo.PtrOp ptr = null; - if( returnInfo.hasPtrOperators() ){ + if( returnInfo.hasPtrOperators() && topPtr.getType() == PtrOp.t_undef ){ ptr = (PtrOp)returnInfo.getPtrOperators().iterator().next(); } else { ptr = new PtrOp(); @@ -1886,336 +1950,6 @@ public class ParserSymbolTable { return returnInfo; } - //TODO Andrew - This code is dead, I didn't cut it out as I assume you plan to make it live soon. Be forewarned. - static private IParameterizedSymbol matchTemplatePartialSpecialization( IParameterizedSymbol template, List args ){ - if( template == null ){ - return null; - } - - List specs = template.getSpecializations(); - int size = ( specs != null ) ? specs.size() : 0; - if( size == 0 ){ - return template; - } - - IParameterizedSymbol bestMatch = null; - boolean bestMatchIsBest = true; - Iterator iter = specs.iterator(); - IParameterizedSymbol spec = null; - List specArgs = null; - for( int i = size; i > 0; i-- ){ - spec = (IParameterizedSymbol) iter.next(); - specArgs = spec.getArgumentList(); - if( specArgs == null || specArgs.size() != args.size() ){ - continue; - } - - ISymbol sym1 = null, sym2 = null; - Iterator iter1 = specArgs.iterator(); - Iterator iter2 = args.iterator(); - - HashMap map = new HashMap(); - //String name = null; - boolean match = true; - for( int j = specArgs.size(); j > 0; j-- ){ - sym1 = (ISymbol)iter1.next(); - TypeInfo info2 = (TypeInfo) iter2.next(); - if( info2.isType( TypeInfo.t_type ) ){ - sym2 = sym2.getTypeSymbol(); - } else { - sym2 = template.getSymbolTable().newSymbol( EMPTY_NAME ); - sym2.setTypeInfo( info2 ); - } - - if( !deduceTemplateArgument( map, sym1, sym2, null ) ){ - match = false; - break; - } - /* - name = sym1.getName(); - if( name.equals( "" ) ){ - //no name, only type - } else if( map.containsKey( name ) ) { - ISymbol val = (ISymbol) map.get( name ); - if( val.getType() != sym2.getType() ){ - match = false; - break; - } - } else { - map.put( name, sym2 ); - } - */ - } - if( match ){ - int compare = orderSpecializations( bestMatch, spec ); - if( compare == 0 ){ - bestMatchIsBest = false; - } else if( compare < 0 ) { - bestMatch = spec; - bestMatchIsBest = true; - } - } - } - - return bestMatchIsBest ? bestMatch : null; - } - - /** - * Compare spec1 to spec2. Return > 0 if spec1 is more specialized, < 0 if spec2 - * is more specialized, = 0 otherwise. - * @param spec1 - * @param spec2 - * @return - */ - static private int orderSpecializations( IParameterizedSymbol spec1, IParameterizedSymbol spec2 ){ - if( spec1 == null ){ - return -1; - } - - Iterator iter = spec1.getContainedSymbols().keySet().iterator(); - ISymbol decl = (ISymbol) spec1.getContainedSymbols().get( iter.next() ); - - //to order class template specializations, we need to transform them into function templates - if( decl.isType( TypeInfo.t_class ) ) { - spec1 = classTemplateSpecializationToFunctionTemplate( spec1 ); - spec2 = classTemplateSpecializationToFunctionTemplate( spec2 ); - } - - TemplateInstance transformed1 = transformFunctionTemplateForOrdering( spec1 ); - TemplateInstance transformed2 = transformFunctionTemplateForOrdering( spec2 ); - - //Using the transformed parameter list, perform argument deduction against the other - //function template - boolean d1 = deduceTemplateArguments( spec2, transformed1 ); - boolean d2 = deduceTemplateArguments( spec1, transformed2 ); - - //The transformed template is at least as specialized as the other iff the deduction - //succeeds and the deduced parameter types are an exact match - //A template is more specialized than another iff it is at least as specialized as the - //other template and that template is not at least as specialized as the first. - if( d1 && d2 || !d1 && !d2 ) - return 0; - else if( d1 && !d2 ) - return 1; - else - return -1; - } - - /** - * - * @param template - * @param args - * @return - * - * A type that is specified in terms of template parameters (P) is compared with an actual - * type (A), and an attempt is made to find template argument vaules that will make P, - * after substitution of the deduced values, compatible with A. - */ - static private boolean deduceTemplateArguments( IParameterizedSymbol template, TemplateInstance argSource ){ - if( template.getContainedSymbols() == null || template.getContainedSymbols().size() != 1 ){ - return false; - } - Iterator iter = template.getContainedSymbols().keySet().iterator(); - ISymbol templateSymbol = (ISymbol) template.getContainedSymbols().get( iter.next() ); - if( !templateSymbol.isType( TypeInfo.t_function ) ){ - return false; - } - - IParameterizedSymbol argTemplate = (IParameterizedSymbol)argSource.getInstantiatedSymbol(); - iter = argTemplate.getContainedSymbols().keySet().iterator(); - ISymbol argFunction = (ISymbol) argTemplate.getContainedSymbols().get( iter.next() ); - if( !argFunction.isType( TypeInfo.t_function ) ){ - return false; - } - - List args = ((IParameterizedSymbol) argFunction).getParameterList(); - - IParameterizedSymbol function = (IParameterizedSymbol) templateSymbol; - - if( function.getParameterList() == null || function.getParameterList().size() != args.size() ){ - return false; - } - - HashMap map = new HashMap(); - - Iterator pIter = function.getParameterList().iterator(); - Iterator aIter = args.iterator(); - while( pIter.hasNext() ){ - if( !deduceTemplateArgument( map, (ISymbol) pIter.next(), (ISymbol) aIter.next(), argSource.getArgumentMap() ) ){ - return false; - } - } - - return true; - } - - static private boolean deduceTemplateArgument( Map map, ISymbol p, ISymbol a, Map argumentMap ){ - if( argumentMap != null && argumentMap.containsKey( a ) ){ - a = (ISymbol) argumentMap.get( a ); - } - - ISymbol pSymbol = p, aSymbol = a; - - if( p.isType( TypeInfo.t_type ) ){ - pSymbol = p.getTypeSymbol(); - aSymbol = a.isType( TypeInfo.t_type ) ? a.getTypeSymbol() : a; - return deduceTemplateArgument( map, pSymbol, aSymbol, argumentMap ); - } else { - if( pSymbol.isTemplateMember() && pSymbol.isType( TypeInfo.t_undef ) ){ - //T* or T& or T[ const ] - //also - List pPtrs = pSymbol.getPtrOperators(); - List aPtrs = aSymbol.getPtrOperators(); - - if( pPtrs != null ){ - TypeInfo.PtrOp pOp = (TypeInfo.PtrOp) pPtrs.iterator().next(); - TypeInfo.PtrOp aOp = ( aPtrs != null ) ? (TypeInfo.PtrOp)pPtrs.iterator().next() : null; - - if( pOp != null && aOp != null && pOp.getType() == aOp.getType() ){ - if( pOp.getType() == TypeInfo.PtrOp.t_memberPointer ){ - - } else { - TypeInfo type = new TypeInfo( aSymbol.getTypeInfo() ); - type.getPtrOperators().clear(); - map.put( pSymbol.getName(), type ); - return true; - } - } else { - return false; - } - } else { - //T - map.put( pSymbol.getName(), a.getTypeInfo() ); - return true; - } - - - } - //template-name or template-name - else if( pSymbol.isType( TypeInfo.t_template ) && aSymbol.isType( TypeInfo.t_template ) ){ - List pArgs = ((IParameterizedSymbol)pSymbol).getArgumentList(); - List aArgs = ((IParameterizedSymbol)aSymbol).getArgumentList(); - - if( pArgs == null || aArgs == null || pArgs.size() != aArgs.size()){ - return false; - } - Iterator pIter = pArgs.iterator(); - Iterator aIter = aArgs.iterator(); - while( pIter.hasNext() ){ - if( !deduceTemplateArgument( map, (ISymbol) pIter.next(), (ISymbol) aIter.next(), argumentMap ) ){ - return false; - } - } - } - //T (*) ( ), T ( T::* ) ( T ), & variations - else if( pSymbol.isType( TypeInfo.t_function ) && aSymbol.isType( TypeInfo.t_function ) ){ - IParameterizedSymbol pFunction = (IParameterizedSymbol)pSymbol; - IParameterizedSymbol aFunction = (IParameterizedSymbol)aSymbol; - - if( !deduceTemplateArgument( map, aFunction.getReturnType(), pFunction.getReturnType(), argumentMap ) ){ - return false; - } - if( pSymbol.getPtrOperators() != null ){ - List ptrs = pSymbol.getPtrOperators(); - TypeInfo.PtrOp op = (TypeInfo.PtrOp) ptrs.iterator().next(); - if( op.getType() == TypeInfo.PtrOp.t_memberPointer ){ - if( !deduceTemplateArgument( map, op.getMemberOf(), pFunction.getContainingSymbol(), argumentMap ) ){ - return false; - } - } - } - - List pParams = pFunction.getParameterList(); - List aParams = aFunction.getParameterList(); - if( pParams.size() != aParams.size() ){ - return false; - } else { - Iterator pIter = pParams.iterator(); - Iterator aIter = aParams.iterator(); - while( pIter.hasNext() ){ - if( !deduceTemplateArgument( map, (ISymbol) pIter.next(), (ISymbol) aIter.next(), argumentMap ) ){ - return false; - } - } - } - - } else if( pSymbol.getType() == aSymbol.getType() ){ - if( pSymbol.getTypeInfo().getHasDefault() ){ - if( !aSymbol.getTypeInfo().getHasDefault() || - aSymbol.getTypeInfo().getDefault().equals( pSymbol.getTypeInfo().getDefault() ) ) - { - return false; - } - } - //value - map.put( pSymbol.getName(), aSymbol.getTypeInfo() ); - return true; - } - } - - return false; - } - /** - * transform the class template to a function template as described in the spec - * 14.5.4.2-1 - * @param template - * @return IParameterizedSymbol - * the function template has the same template parameters as the partial specialization and - * has a single function parameter whose type is a class template specialization with the template - * arguments of the partial specialization - */ - static private IParameterizedSymbol classTemplateSpecializationToFunctionTemplate( IParameterizedSymbol template ){ - IParameterizedSymbol transformed = (IParameterizedSymbol) template.clone(); - transformed.getArgumentList().clear(); - transformed.getContainedSymbols().clear(); - - IParameterizedSymbol function = template.getSymbolTable().newParameterizedSymbol( transformed.getName(), TypeInfo.t_function ); - try{ - transformed.addSymbol( function ); - } catch ( ParserSymbolTableException e ){ - //we shouldn't get this because there aren't any other symbols in the template - } - - function.addParameter( template ); - - return transformed; - } - - /** - * transform a function template for use in partial ordering, as described in the - * spec 14.5.5.2-3 - * @param template - * @return - * -for each type template parameter, synthesize a unique type and substitute that for each - * occurence of that parameter in the function parameter list - * -for each non-type template parameter, synthesize a unique value of the appropriate type and - * susbstitute that for each occurence of that parameter in the function parameter list - * for each template template parameter, synthesize a unique class template and substitute that - * for each occurence of that parameter in the function parameter list - */ - static private TemplateInstance transformFunctionTemplateForOrdering( IParameterizedSymbol template ){ - - List paramList = template.getParameterList(); - - int size = ( paramList != null ) ? paramList.size() : 0; - if( size == 0 ){ - return null; - } - - HashMap map = new HashMap(); - for( Iterator iterator = paramList.iterator(); iterator.hasNext(); ) { - ISymbol param = (ISymbol) iterator.next(); - ISymbol val = template.getSymbolTable().newSymbol( EMPTY_NAME, TypeInfo.t_type ); - if( false /* is value */ ){ - //val.getTypeInfo().setHasDefault() - } - map.put( param, val ); - } - - return new TemplateInstance( template.getSymbolTable(), template, map ); - } - - //private Stack _contextStack = new Stack(); private IContainerSymbol _compilationUnit; private ParserLanguage _language; private ParserMode _mode; @@ -2302,10 +2036,11 @@ public class ParserSymbolTable { public HashSet inheritanceChain; //used to detect circular inheritance - public List parameters; //parameter info for resolving functions + public List parameters; //parameter info for resolving functions public HashSet associated; //associated namespaces for argument dependant lookup public ISymbol stopAt; //stop looking along the stack once we hit this declaration public TypeFilter filter = null; + public ISymbol templateMember; //to assit with template member defs public boolean qualified = false; public boolean ignoreUsingDirectives = false; @@ -2314,22 +2049,19 @@ public class ParserSymbolTable { public Map foundItems = null; - public ISymbol templateInstance = null; public LookupMode mode = LookupMode.NORMAL; - public LookupData( String n, TypeInfo.eType t, ISymbol i ){ + public LookupData( String n, TypeInfo.eType t ){ name = n; filter = new TypeFilter( t ); - templateInstance = i; } - public LookupData( String n, TypeFilter f, ISymbol i ){ + public LookupData( String n, TypeFilter f ) { name = n; filter = ( f != null ) ? f : new TypeFilter( TypeInfo.t_any ); - templateInstance = i; } } - static private class Cost + static protected class Cost { public Cost( TypeInfo s, TypeInfo t ){ @@ -2445,7 +2177,7 @@ public class ParserSymbolTable { * @param qualifyingSymbol * @return */ - public static ASTAccessVisibility getVisibility(ISymbol symbol, IContainerSymbol qualifyingSymbol) throws ParserSymbolTableException { + public static ASTAccessVisibility getVisibility(ISymbol symbol, IContainerSymbol qualifyingSymbol){ IContainerSymbol container = symbol.getContainingSymbol(); if( qualifyingSymbol == null || container.equals( qualifyingSymbol ) ){ @@ -2454,12 +2186,12 @@ public class ParserSymbolTable { if( node != null && node instanceof IASTMember ){ return ((IASTMember)node).getVisiblity(); } else { - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); } } if( ! (qualifyingSymbol instanceof IDerivableContainerSymbol) ){ - throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); } List parents = ((IDerivableContainerSymbol) qualifyingSymbol).getParents(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableError.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableError.java new file mode 100644 index 00000000000..af45971b2be --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableError.java @@ -0,0 +1,36 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +/** + * @author aniefer + */ +public class ParserSymbolTableError extends Error { + /** + * Constructor for ParserSymbolTableError. + */ + public ParserSymbolTableError() { + super(); + } + + /** + * Constructor for ParserSymbolTableError. + * @param int r: reason + */ + public ParserSymbolTableError( int r ) { + reason = r; + } + + public static final int r_InternalError = -1; + public static final int r_OperationNotSupported = 0; + public int reason = -1; + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java index b562e49fddc..9f5de6f208a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTableException.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2002,2003 Rational Software Corporation and others. + * Copyright (c) 2002,2003, 2004 Rational Software Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -13,11 +13,6 @@ package org.eclipse.cdt.internal.core.parser.pst; /** * @author aniefer - * - * To change this generated comment edit the template variable "typecomment": - * Window>Preferences>Java>Templates. - * To enable and disable the creation of type comments go to - * Window>Preferences>Java>Code Generation. */ public class ParserSymbolTableException extends Exception { @@ -36,15 +31,18 @@ public class ParserSymbolTableException extends Exception { reason = r; } - public static final int r_InternalError = -1; - public static final int r_Ambiguous = 0; - public static final int r_BadTypeInfo = 1; - public static final int r_CircularInheritance = 2; - public static final int r_InvalidOverload = 3; - public static final int r_BadTemplate = 4; - public static final int r_InvalidUsing = 5; - public static final int r_BadVisibility = 6; - public static final int r_UnableToResolveFunction = 7; - + public static final int r_InternalError = -1; + public static final int r_Ambiguous = 0; + public static final int r_BadTypeInfo = 1; + public static final int r_CircularInheritance = 2; + public static final int r_InvalidOverload = 3; + public static final int r_BadTemplate = 4; + public static final int r_InvalidUsing = 5; + public static final int r_BadVisibility = 6; + public static final int r_UnableToResolveFunction = 7; + public static final int r_BadTemplateArgument = 8; + public static final int r_BadTemplateParameter = 9; + public static final int r_RedeclaredTemplateParam = 10; public int reason = -1; + } \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java index f6b6c331cbb..d87afc76858 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/SpecializedSymbol.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. + * Copyright (c) 2003, 2004 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -13,18 +13,146 @@ */ package org.eclipse.cdt.internal.core.parser.pst; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.Command; + /** - * @author aniefer - * - * To change the template for this generated type comment go to - * Window>Preferences>Java>Code Generation>Code and Comments + * @author aniefe */ -public class SpecializedSymbol extends ParameterizedSymbol implements ISpecializedSymbol { + +public class SpecializedSymbol extends TemplateSymbol implements ISpecializedSymbol { protected SpecializedSymbol( ParserSymbolTable table, String name ){ - super( table, name, TypeInfo.t_template ); + super( table, name ); } protected SpecializedSymbol( ParserSymbolTable table, String name, ISymbolASTExtension obj ){ super( table, name, obj ); } + + public Object clone(){ + SpecializedSymbol copy = (SpecializedSymbol)super.clone(); + + copy._argumentList = ( _argumentList != null ) ? (LinkedList) _argumentList.clone() : null; + + return copy; + } + + + public ITemplateSymbol getPrimaryTemplate(){ + return _primaryTemplate; + } + + public void setPrimaryTemplate( ITemplateSymbol templateSymbol ){ + _primaryTemplate = templateSymbol; + } + + public ISymbol instantiate( List arguments ) throws ParserSymbolTableException{ + Map argMap = new HashMap(); + + List specArgs = getArgumentList(); + if( specArgs.size() != arguments.size() ){ + return null; + } + + List actualArgs = new LinkedList(); + + Iterator iter1 = specArgs.iterator(); + Iterator iter2 = arguments.iterator(); + + ISymbol templatedSymbol = getTemplatedSymbol(); + while( templatedSymbol.isTemplateInstance() ){ + templatedSymbol = templatedSymbol.getInstantiatedSymbol(); + } + + while( iter1.hasNext() ){ + TypeInfo info = (TypeInfo) iter1.next(); + TypeInfo mappedInfo = (TypeInfo) iter2.next(); + + //If the argument is a template parameter, we can't instantiate yet, defer for later + if( mappedInfo.isType( TypeInfo.t_type ) && mappedInfo.getTypeSymbol().isType( TypeInfo.t_templateParameter ) ){ + return deferredInstance( arguments ); + } + + actualArgs.add( mappedInfo ); + if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol().isType( TypeInfo.t_templateParameter )){ + ISymbol param = info.getTypeSymbol(); + + param = TemplateEngine.translateParameterForDefinition ( templatedSymbol, param, getDefinitionParameterMap() ); + + if( !argMap.containsKey( param ) ){ + argMap.put( param, mappedInfo ); + } + } + } + + //sanity check + if( getParameterList().size() != argMap.size() ) + return null; + + Iterator params = getParameterList().iterator(); + while( params.hasNext() ){ + if( !argMap.containsKey( params.next() ) ) + return null; + } + + IContainerSymbol instance = findInstantiation( actualArgs ); + if( instance != null ){ + return instance; + } else { + IContainerSymbol symbol = null; + + if( getContainedSymbols().size() == 1 ){ + Iterator iter = getContainedSymbols().keySet().iterator(); + symbol = (IContainerSymbol)getContainedSymbols().get( iter.next() ); + } + + instance = (IContainerSymbol) symbol.instantiate( this, argMap ); + addInstantiation( instance, actualArgs ); + return instance; + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getArgumentList() + */ + public List getArgumentList(){ + if( _argumentList == null ){ + _argumentList = new LinkedList(); + } + return _argumentList; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addArgument(org.eclipse.cdt.internal.core.parser.pst.ISymbol) + */ + public void addArgument(TypeInfo arg) { + List argumentList = getArgumentList(); + argumentList.add( arg ); + + //arg.setIsTemplateMember( isTemplateMember() || getType() == TypeInfo.t_template ); + + Command command = new AddArgumentCommand( this, arg ); + getSymbolTable().pushCommand( command ); + } + + static private class AddArgumentCommand extends Command{ + public AddArgumentCommand( ISpecializedSymbol container, TypeInfo arg ){ + _decl = container; + _arg = arg; + } + public void undoIt(){ + _decl.getArgumentList().remove( _arg ); + } + + private ISpecializedSymbol _decl; + private TypeInfo _arg; + } + + private LinkedList _argumentList; //template specialization arguments + private ITemplateSymbol _primaryTemplate; //our primary template } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java new file mode 100644 index 00000000000..baac4349837 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateEngine.java @@ -0,0 +1,1132 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.internal.core.parser.pst.IDerivableContainerSymbol.IParentSymbol; +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.Cost; +import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp; + +/** + * @author aniefer + */ +public final class TemplateEngine { + + static protected TypeInfo instantiateTypeInfo( TypeInfo info, ITemplateSymbol template, Map argMap ) throws ParserSymbolTableException{ + if( argMap == null ){ + return info; + } else { + if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol() instanceof IDeferredTemplateInstance ){ + IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) info.getTypeSymbol(); + + TypeInfo newInfo = new TypeInfo( info ); + newInfo.setTypeSymbol( deferred.instantiate( template, argMap ) ); + return newInfo; + } else if( info.isType( TypeInfo.t_type ) && + info.getTypeSymbol().isType( TypeInfo.t_templateParameter ) && + argMap.containsKey( info.getTypeSymbol() ) ) + { + TypeInfo targetInfo = new TypeInfo( (TypeInfo) argMap.get( info.getTypeSymbol() ) ); + if( info.hasPtrOperators() ){ + List infoOperators = new LinkedList( info.getPtrOperators() ); + + if( targetInfo.hasPtrOperators() ){ + List targetOperators = targetInfo.getPtrOperators(); + + PtrOp lastTargetOp = (PtrOp) targetOperators.get( targetOperators.size() - 1 ); + if( lastTargetOp.getType() == PtrOp.t_undef ){ + targetOperators.remove( targetOperators.size() - 1 ); + PtrOp infoOp = (PtrOp) infoOperators.get( 0 ); + infoOp = new PtrOp( infoOp.getType(), infoOp.isConst() || lastTargetOp.isConst(), + infoOp.isVolatile() || lastTargetOp.isVolatile() ); + infoOperators.set( 0, infoOp ); + } + } + + targetInfo.addPtrOperator( infoOperators ); + } + return targetInfo; + } else if( info.isType( TypeInfo.t_type ) && info.getTypeSymbol().isType( TypeInfo.t_function ) ){ + TypeInfo newInfo = new TypeInfo( info ); + newInfo.setTypeSymbol( info.getTypeSymbol().instantiate( template, argMap ) ); + return newInfo; + } + return info; + } + } + + static protected ITemplateSymbol matchTemplatePartialSpecialization( ITemplateSymbol template, List args ) throws ParserSymbolTableException{ + if( template == null ){ + return null; + } + + List specs = template.getSpecializations(); + int size = ( specs != null ) ? specs.size() : 0; + if( size == 0 ){ + return template; + } + + ISpecializedSymbol bestMatch = null; + boolean bestMatchIsBest = true; + Iterator iter = specs.iterator(); + ISpecializedSymbol spec = null; + List specArgs = null; + for( int i = size; i > 0; i-- ){ + spec = (ISpecializedSymbol) iter.next(); + specArgs = spec.getArgumentList(); + if( specArgs == null || specArgs.size() != args.size() ){ + continue; + } + + Iterator iter1 = specArgs.iterator(); + Iterator iter2 = args.iterator(); + + HashMap map = new HashMap(); + TypeInfo info1 = null, info2 = null; + + boolean match = true; + for( int j = specArgs.size(); j > 0; j-- ){ + info1 = (TypeInfo) iter1.next(); + info2 = (TypeInfo) iter2.next(); + + ISymbol sym1 = template.getSymbolTable().newSymbol( ParserSymbolTable.EMPTY_NAME ); + sym1.setTypeInfo( info1 ); + + if( !deduceTemplateArgument( map, sym1, info2 ) ){ + match = false; + break; + } + } + if( match ){ + int compare = orderSpecializations( bestMatch, spec ); + if( compare == 0 ){ + bestMatchIsBest = false; + } else if( compare < 0 ) { + bestMatch = spec; + bestMatchIsBest = true; + } + } + } + + //14.5.4.1 If none of the specializations is more specialized than all the other matchnig + //specializations, then the use of the class template is ambiguous and the program is ill-formed. + if( !bestMatchIsBest ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); + } + + return bestMatch; + } + + static protected boolean matchTemplateParameterAndArgument( ISymbol param, TypeInfo arg ){ + if( !isValidArgument(param, arg) ){ + return false; + } + + if( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_typeName ){ + return true; + } else if( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_template ){ + + ISymbol symbol = arg.getTypeSymbol(); + if( !arg.isType( TypeInfo.t_type ) || symbol == null || !symbol.isType( TypeInfo.t_template ) ){ + return false; + } + + IParameterizedSymbol p = (IParameterizedSymbol) param; + IParameterizedSymbol a = (IParameterizedSymbol) symbol; + + List pList = p.getParameterList(); + List aList = a.getParameterList(); + + if( pList.size() != aList.size() ){ + return false; + } + + Iterator pIter = pList.iterator(); + Iterator aIter = aList.iterator(); + while( pIter.hasNext() ){ + ISymbol pParam = (ISymbol) pIter.next(); + ISymbol aParam = (ISymbol) aIter.next(); + + if( pParam.getType() != aParam.getType() || + pParam.getTypeInfo().getTemplateParameterType() != aParam.getTypeInfo().getTemplateParameterType() ) + { + return false; + } + } + + return true; + } else { + Cost cost = null; + try { + cost = ParserSymbolTable.checkStandardConversionSequence( arg, param.getTypeInfo()); + } catch (ParserSymbolTableException e) { + } + + if( cost == null || cost.rank != Cost.NO_MATCH_RANK ){ + return false; + } + } + return true; + } + + static private boolean isValidArgument(ISymbol param, TypeInfo arg) { + if( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_typeName ){ + //14.3.1, local type, type with no name + if( arg.isType( TypeInfo.t_type ) && arg.getTypeSymbol() != null ){ + ISymbol symbol = arg.getTypeSymbol(); + if( symbol.getName().equals( ParserSymbolTable.EMPTY_NAME ) ){ + return false; + } else if( hasNoLinkage( arg ) ){ + return false; + } + } + } else if ( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_template ){ + + } else { + List ptrs = param.getPtrOperators(); + PtrOp op = ( ptrs.size() > 0 ) ? (PtrOp) ptrs.get(0) : null; + + //if the parameter has reference type + if( op != null && op.getType() == PtrOp.t_reference ){ + if( arg.isType( TypeInfo.t_type ) && arg.getTypeSymbol() != null ){ + if( arg.getTypeSymbol().getName().equals( ParserSymbolTable.EMPTY_NAME ) ){ + return false; + } + } + return hasExternalLinkage( arg ); + } + + List argPtrs = arg.getPtrOperators(); + PtrOp argOp = (argPtrs.size() > 0 ) ? (PtrOp)argPtrs.get(0) : null; + + //address of an object with external linkage exluding nonstatic class members + //name of an object with external linkage excluding nonstatic class members + if( (argOp != null && argOp.getType() == PtrOp.t_pointer ) || + ( arg.isType( TypeInfo.t_type ) ) ) + { + ISymbol symbol = arg.getTypeSymbol(); + if ( symbol != null && symbol.getContainingSymbol().isType( TypeInfo.t_class, TypeInfo.t_union ) ){ + if( !symbol.isType( TypeInfo.t_class, TypeInfo.t_union ) ){ + if( !symbol.getTypeInfo().checkBit( TypeInfo.isStatic ) ){ + return false; + } + } + } + + return hasExternalLinkage( arg ); + } + + //integral or enumeration type + if( op == null && ( arg.isType( TypeInfo.t_bool, TypeInfo.t_int ) || + arg.isType( TypeInfo.t_enumerator ) ) ) + { + return true; + } + + //name of a non-type template parameter + if( arg.isType( TypeInfo.t_templateParameter ) && + arg.getTemplateParameterType() != TypeInfo.t_typeName && + arg.getTemplateParameterType() != TypeInfo.t_template ) + { + return true; + } + return false; + } + return true; + } + + static protected boolean hasExternalLinkage( TypeInfo type ){ + if( ! type.isType( TypeInfo.t_type ) ) + return false; + + return !hasNoLinkage( type ); + } + + static protected boolean hasInternalLinkage( TypeInfo type ){ + return !hasNoLinkage( type ); + } + + static protected boolean hasNoLinkage( TypeInfo type ){ + if( type.isType( TypeInfo.t_type ) ){ + ISymbol symbol = type.getTypeSymbol(); + if( symbol.getContainingSymbol() == null ){ + return true; //a temporary + } + + return symbol.getContainingSymbol().isType( TypeInfo.t_function ); + } + + return false; + } + + /** + * 14.8.2.1-2 If P is a cv-qualified type, the top level cv-qualifiers of P's type are ignored for type + * deduction. If P is a reference type, the type referred to by P is used for Type deduction. + * @param pSymbol + * @return + */ + static private TypeInfo getParameterTypeForDeduction( ISymbol pSymbol ){ + TypeInfo p = new TypeInfo( pSymbol.getTypeInfo () ); + List pPtrs = p.getPtrOperators(); + if( pPtrs.size() > 0 ){ + PtrOp pOp = (PtrOp) pPtrs.get( 0 ); + if( pOp.getType() == PtrOp.t_reference || pOp.getType() == PtrOp.t_undef ){ + pPtrs.remove( 0 ); + } else { + PtrOp newOp = new PtrOp( pOp.getType(), false, false ); + pPtrs.set( 0, newOp ); + } + } + + return p; + } + + /** + * 14.8.2.1-2 + * - If A is an array type, the pointer type produced by the array-to-pointer conversion is used instead + * - If A is a function type, the pointer type produced by the function-to-pointer conversion is used instead + * - If A is a cv-qualified type, the top level cv-qualifiers are ignored for type deduction + * @param aInfo + * @return + */ + static private TypeInfo getArgumentTypeForDeduction( TypeInfo aInfo ){ + + TypeInfo a = ParserSymbolTable.getFlatTypeInfo( aInfo ); + + List aPtrs = a.getPtrOperators(); + ISymbol aSymbol = a.getTypeSymbol(); + + if( a.getType() == TypeInfo.t_type && aSymbol.isType( TypeInfo.t_function ) ){ + if( aPtrs.size() == 0 ){ + aPtrs.add( new PtrOp( PtrOp.t_pointer ) ); + } + } + if( aPtrs.size() > 0 ){ + PtrOp pOp = (PtrOp) aPtrs.get( 0 ); + + if( pOp.getType() == PtrOp.t_array ){ + aPtrs.set( 0, new PtrOp( PtrOp.t_pointer, false, false ) ); + } else if( pOp.getType() == PtrOp.t_undef ){ + aPtrs.remove( 0 ); + } else { + aPtrs.set( 0, new PtrOp( pOp.getType(), false, false ) ); + } + } + + return a; + } + + static private List getSourceList( ISymbol symbol ){ + ITemplateSymbol template = null; + + if( symbol instanceof IDeferredTemplateInstance ){ + IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) symbol; + return deferred.getArguments(); + } else { + ISymbol instantiated = symbol.getInstantiatedSymbol(); + template = (ITemplateSymbol) instantiated.getContainingSymbol(); + } + + if( template instanceof ISpecializedSymbol ){ + return ((ISpecializedSymbol)template).getArgumentList(); + } else { + return template.getParameterList(); + } + } + + static private List getTargetList( ISymbol symbol ){ + if( symbol instanceof IDeferredTemplateInstance ){ + IDeferredTemplateInstance deferred = (IDeferredTemplateInstance) symbol; + return deferred.getArguments(); + } else { + ISymbol instantiated = symbol.getInstantiatedSymbol(); + ITemplateSymbol template = (ITemplateSymbol) instantiated.getContainingSymbol(); + return template.findArgumentsFor( (IContainerSymbol) symbol ); + } + } + + /** + * @param aSymbol + * @param p + * @param derivable + * @return + */ + private static ISymbol findMatchingBaseClass( ISymbol p, IDerivableContainerSymbol a ) { + ISymbol aSymbol = null; + ITemplateSymbol pTemplate = null; + ITemplateSymbol parentTemplate = null; + + if( p instanceof IDeferredTemplateInstance ){ + pTemplate = ((IDeferredTemplateInstance)p).getTemplate(); + } else { + pTemplate = (ITemplateSymbol) p.getInstantiatedSymbol().getContainingSymbol(); + } + if( pTemplate instanceof ISpecializedSymbol ){ + pTemplate = ((ISpecializedSymbol)pTemplate).getPrimaryTemplate(); + } + Iterator iter = a.getParents().iterator(); + while( iter.hasNext() ){ + IParentSymbol wrapper = (IParentSymbol) iter.next(); + ISymbol parent = wrapper.getParent(); + if( parent instanceof IDeferredTemplateInstance ){ + IDeferredTemplateInstance parentInstance = (IDeferredTemplateInstance) parent; + parentTemplate = parentInstance.getTemplate(); + if( parentTemplate instanceof ISpecializedSymbol ){ + parentTemplate = ((ISpecializedSymbol)parentTemplate).getPrimaryTemplate(); + } + if( pTemplate == parentTemplate ){ + aSymbol = parent; + break; + } + //In general, we don't have enough information to proceed further down this branch + } else { + parentTemplate = (ITemplateSymbol) parent.getInstantiatedSymbol().getContainingSymbol(); + if( parentTemplate instanceof ISpecializedSymbol ){ + parentTemplate = ((ISpecializedSymbol)parentTemplate).getPrimaryTemplate(); + } + if( pTemplate == parentTemplate ){ + aSymbol = parent; + break; + } + aSymbol = findMatchingBaseClass( p, (IDerivableContainerSymbol) parent ); + } + if( aSymbol != null ) + return aSymbol; + } + + return aSymbol; + } + + static private boolean deduceTemplateArgument( Map map, ISymbol pSymbol, TypeInfo a ){//, Map argumentMap ){ + ISymbol symbol; + + TypeInfo p = getParameterTypeForDeduction( pSymbol ); + a = getArgumentTypeForDeduction( a ); + + if( p.isType( TypeInfo.t_type ) ){ + symbol = p.getTypeSymbol(); + ISymbol aSymbol = a.getTypeSymbol(); + if( symbol instanceof IDeferredTemplateInstance || symbol.isTemplateInstance() ){ + return deduceFromTemplateTemplateArguments(map, symbol, aSymbol); + } else { + if( symbol.isType( TypeInfo.t_templateParameter ) ){ + if( symbol.getTypeInfo().getTemplateParameterType() == TypeInfo.t_typeName ){ + //a = getFlatTypeInfo( a ); + List aPtrs = a.getPtrOperators(); + List pPtrs = p.getPtrOperators(); + //TODO cvlist T + if( pPtrs != null && pPtrs.size() > 0){ + if( aPtrs == null ){ + return false; + } + + Iterator pIter = pPtrs.iterator(); + ListIterator aIter = aPtrs.listIterator(); + PtrOp pOp = null; + PtrOp aOp = null; + while( pIter.hasNext() ){ + pOp = (PtrOp) pIter.next(); + if( !aIter.hasNext() ){ + return false; + } else { + aOp = (PtrOp) aIter.next(); + if( pOp.getType() == aOp.getType() ){ + if( !pOp.equals( aOp ) ){ + if( pIter.hasNext() || pOp.compareCVTo( aOp ) > 0 ){ + return false; + } else { + PtrOp newOp = new PtrOp( PtrOp.t_undef ); + newOp.setConst( aOp.isConst() ); + newOp.setVolatile( aOp.isVolatile() ); + aIter.set( newOp ); + } + } else { + aIter.remove(); + } + + } else { + return false; + } + } + } + return deduceArgument( map, symbol, a ); + } else { + //T + return deduceArgument( map, symbol, a ); + } + } else if ( symbol.getTypeInfo().getTemplateParameterType() == TypeInfo.t_template ){ + + } else { + //non-type parameter + if( symbol.getTypeInfo().getTemplateParameterType() == a.getType() ){ + return deduceArgument( map, symbol, a ); + } else { + return false; + } + + } + } + //T (*) ( ), T ( T::* ) ( T ), & variations + else if( symbol.isType( TypeInfo.t_function ) ){ + if( !(aSymbol instanceof IParameterizedSymbol)|| + !aSymbol.isType( TypeInfo.t_function ) ) + { + return false; + } + + IParameterizedSymbol pFunction = (IParameterizedSymbol)symbol; + IParameterizedSymbol aFunction = (IParameterizedSymbol)aSymbol; + + if( !deduceTemplateArgument( map, pFunction.getReturnType(), aFunction.getReturnType().getTypeInfo() ) ){ + return false; + } + + List pPtrs = p.getPtrOperators(); + if( pPtrs.size() != 0 ){ + PtrOp op = (PtrOp) pPtrs.iterator().next();; + if( op.getType() == PtrOp.t_memberPointer ){ + TypeInfo info = new TypeInfo( TypeInfo.t_type, 0, aFunction.getContainingSymbol() ); + if( !deduceTemplateArgument( map, op.getMemberOf(), info ) ){ + return false; + } + } + } + + List pParams = pFunction.getParameterList(); + List aParams = aFunction.getParameterList(); + if( pParams.size() != aParams.size() ){ + return false; + } else { + Iterator pIter = pParams.iterator(); + Iterator aIter = aParams.iterator(); + while( pIter.hasNext() ){ + TypeInfo info = ((ISymbol)aIter.next()).getTypeInfo(); + if( !deduceTemplateArgument( map, (ISymbol) pIter.next(), info ) ){ + return false; + } + } + } + return true; + } + } + } else { + if( p.isType( TypeInfo.t_templateParameter ) ){ + return deduceArgument( map, pSymbol, a ); + } + if( p.getType() == a.getType() ){ + if( p.getDefault() != null ){ + return ( p.getDefault().equals( a.getDefault() ) ); + } + return true; + } + } + + return false; + } + + /** + * @param map + * @param pSymbol + * @param transformationMap + * @param symbol + * @param aSymbol + * @return + */ + private static boolean deduceFromTemplateTemplateArguments(Map map, ISymbol pSymbol, ISymbol aSymbol) { + //template-name or template-name, where template-name is a class template + ITemplateSymbol p = ( pSymbol instanceof IDeferredTemplateInstance ) ? + (ITemplateSymbol) ((IDeferredTemplateInstance) pSymbol ).getTemplate() : + (ITemplateSymbol) pSymbol.getInstantiatedSymbol().getContainingSymbol(); + + if( p instanceof ISpecializedSymbol ) + p = ((ISpecializedSymbol)p).getPrimaryTemplate(); + + ISymbol a = ( aSymbol.isTemplateInstance() ) ? aSymbol.getInstantiatedSymbol().getContainingSymbol() : + aSymbol.getContainingSymbol(); + + if( a instanceof ISpecializedSymbol ) + a = ((ISpecializedSymbol)a).getPrimaryTemplate(); + + if( p != a ){ + if( aSymbol instanceof IDerivableContainerSymbol ){ + aSymbol = findMatchingBaseClass( pSymbol, (IDerivableContainerSymbol) aSymbol ); + } else { + aSymbol = null; + } + if( aSymbol == null ) { + return false; + } + } + + List pList = getSourceList( pSymbol ); + List aList = getTargetList( aSymbol ); + + //TODO: default args? + if( pList == null || aList == null || pList.size() != aList.size()){ + return false; + } + Iterator pIter = pList.iterator(); + Iterator aIter = aList.iterator(); + while( pIter.hasNext() ){ + Object obj = pIter.next(); + ISymbol sym = null; + if( obj instanceof ISymbol ){ + sym = (ISymbol) obj; + } else { + sym = pSymbol.getSymbolTable().newSymbol( ParserSymbolTable.EMPTY_NAME ); + sym.setTypeInfo( (TypeInfo) obj ); + } + + TypeInfo arg = transformTypeInfo( aIter.next(), null ); + + if( !deduceTemplateArgument( map, sym, arg ) ){ + return false; + } + } + return true; + } + + /** + * + * @param template + * @param argList - the arguments passed in the function call + * @return + * + * A type that is specified in terms of template parameters (P) is compared with an actual + * type (A), and an attempt is made to find template argument vaules that will make P, + * after substitution of the deduced values, compatible with A. + */ + static private Map deduceTemplateArgumentsUsingParameterList( ITemplateSymbol template, IParameterizedSymbol function ){ + + List aList = function.getParameterList(); + LinkedList args = new LinkedList(); + + Iterator iter = aList.iterator(); + while( iter.hasNext() ){ + ISymbol symbol = (ISymbol) iter.next(); + args.add( symbol.getTypeInfo() ); + } + + return deduceTemplateArguments( template, args ); + } + /** + * + * @param template + * @param args + * @return + * + * A type that is specified in terms of template parameters (P) is compared with an actual + * type (A), and an attempt is made to find template argument vaules that will make P, + * after substitution of the deduced values, compatible with A. + */ + static private Map deduceTemplateArguments( IParameterizedSymbol template, List arguments ){ + if( template.getContainedSymbols() == null || template.getContainedSymbols().size() != 1 ){ + return null; + } + Iterator iter = template.getContainedSymbols().keySet().iterator(); + ISymbol templateSymbol = (ISymbol) template.getContainedSymbols().get( iter.next() ); + if( !templateSymbol.isType( TypeInfo.t_function ) ){ + return null; + } + + IParameterizedSymbol templateFunction = (IParameterizedSymbol) templateSymbol; + + List pList = templateFunction.getParameterList(); +// TODO: ellipses? + if( pList == null || arguments == null || pList.size() != arguments.size() ){ + return null; + } + + HashMap map = new HashMap(); + + Iterator pIter = pList.iterator(); + Iterator aIter = arguments.iterator(); + + ISymbol aSymbol = null; + while( pIter.hasNext() ){ + if( !deduceTemplateArgument( map, (ISymbol) pIter.next(), (TypeInfo) aIter.next() ) ){ + return null; + } + } + + return map; + } + + static private boolean deduceArgument( Map map, ISymbol p, TypeInfo a ){ + + a = ParserSymbolTable.getFlatTypeInfo( a ); + + if( map.containsKey( p ) ){ + TypeInfo current = (TypeInfo)map.get( p ); + return current.equals( a ); + } else { + map.put( p, a ); + return true; + } + } + /** + * Compare spec1 to spec2. Return > 0 if spec1 is more specialized, < 0 if spec2 + * is more specialized, = 0 otherwise. + * @param spec1 + * @param spec2 + * @return + */ + static private int orderSpecializations( ISpecializedSymbol spec1, ISpecializedSymbol spec2 ) throws ParserSymbolTableException{ + if( spec1 == null ){ + return -1; + } + + Iterator iter = spec1.getContainedSymbols().keySet().iterator(); + ISymbol decl = (ISymbol) spec1.getContainedSymbols().get( iter.next() ); + + //to order class template specializations, we need to transform them into function templates + ITemplateSymbol template1 = spec1; + ITemplateSymbol template2 = spec2; + + if( decl.isType( TypeInfo.t_class ) ) { + template1 = classTemplateSpecializationToFunctionTemplate( spec1 ); + template2 = classTemplateSpecializationToFunctionTemplate( spec2 ); + } + + return orderTemplateFunctions( template1, template2); + } + + /** + * Compare spec1 to spec2. Return > 0 if spec1 is more specialized, < 0 if spec2 + * is more specialized, = 0 otherwise. + * + * Both spec1 and spec2 are expected to be template functions + * + */ + static protected int orderTemplateFunctions( ITemplateSymbol spec1, ITemplateSymbol spec2 ) throws ParserSymbolTableException{ + //Using the transformed parameter list, perform argument deduction against the other + //function template + Map map = createMapForFunctionTemplateOrdering( spec1 ); + + IContainerSymbol templatedSymbol = spec1.getTemplatedSymbol(); + if( !( templatedSymbol instanceof IParameterizedSymbol ) ) + throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + + IParameterizedSymbol function = (IParameterizedSymbol)templatedSymbol; + function = (IParameterizedSymbol) function.instantiate( spec1, map ); + + Map m1 = deduceTemplateArgumentsUsingParameterList( spec2, function); + + map = createMapForFunctionTemplateOrdering( spec2 ); + + templatedSymbol = spec2.getTemplatedSymbol(); + if( !( templatedSymbol instanceof IParameterizedSymbol ) ) + throw new ParserSymbolTableException( ParserSymbolTableException.r_InternalError ); + + function = (IParameterizedSymbol)templatedSymbol; + function = (IParameterizedSymbol) function.instantiate( spec2, map ); + + Map m2 = deduceTemplateArgumentsUsingParameterList( spec1, function ); + + //The transformed template is at least as specialized as the other iff the deduction + //succeeds and the deduced parameter types are an exact match + //A template is more specialized than another iff it is at least as specialized as the + //other template and that template is not at least as specialized as the first. + boolean d1 = ( m1 != null ); + boolean d2 = ( m2 != null ); + + if( d1 && d2 || !d1 && !d2 ) + return 0; + else if( d1 && !d2 ) + return 1; + else + return -1; + } + + /** + * transform a function template for use in partial ordering, as described in the + * spec 14.5.5.2-3 + * @param template + * @return + * -for each type template parameter, synthesize a unique type and substitute that for each + * occurence of that parameter in the function parameter list + * -for each non-type template parameter, synthesize a unique value of the appropriate type and + * susbstitute that for each occurence of that parameter in the function parameter list + * for each template template parameter, synthesize a unique class template and substitute that + * for each occurence of that parameter in the function parameter list + */ + + static private Map createMapForFunctionTemplateOrdering( ITemplateSymbol template ){ + HashMap map = new HashMap(); + TypeInfo val = null; + List paramList = template.getParameterList(); + for( Iterator iterator = paramList.iterator(); iterator.hasNext(); ) { + ISymbol param = (ISymbol) iterator.next(); + //template type parameter + if( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_typeName ){ + val = new TypeInfo( TypeInfo.t_type, 0, template.getSymbolTable().newSymbol( "", TypeInfo.t_class ) ); + } + //template parameter + else if ( param.getTypeInfo().getTemplateParameterType() == TypeInfo.t_template ) { + + } + //non type parameter + else { + val = new TypeInfo( param.getTypeInfo().getTemplateParameterType(), 0, null ); + } + map.put( param, val ); + } + return map; + } + + + /** + * transform the class template to a function template as described in the spec + * 14.5.4.2-1 + * @param template + * @return IParameterizedSymbol + * the function template has the same template parameters as the partial specialization and + * has a single function parameter whose type is a class template specialization with the template + * arguments of the partial specialization + */ + static private ITemplateSymbol classTemplateSpecializationToFunctionTemplate( ISpecializedSymbol specialization ) throws ParserSymbolTableException{ + ISpecializedSymbol transformed = (ISpecializedSymbol) specialization.clone(); + transformed.getArgumentList().clear(); + transformed.getContainedSymbols().clear(); + //TODO clean up this + ((ContainerSymbol)transformed).getContents().clear(); + + IParameterizedSymbol function = specialization.getSymbolTable().newParameterizedSymbol( transformed.getName(), TypeInfo.t_function ); + try{ + transformed.addSymbol( function ); + } catch ( ParserSymbolTableException e ){ + //we shouldn't get this because there aren't any other symbols in the template + } + ISymbol param = specialization.getSymbolTable().newSymbol( "", TypeInfo.t_type ); + LinkedList args = new LinkedList( specialization.getArgumentList() ); + + param.setTypeSymbol( specialization.instantiate( args ) ); + + function.addParameter( param ); + + return transformed; + } + + static private TypeInfo transformTypeInfo( Object obj, Map argumentMap ){ + TypeInfo info = null; + if( obj instanceof ISymbol ){ + info = new TypeInfo( TypeInfo.t_type, 0, (ISymbol) obj ); + } else { + info = (TypeInfo) obj; + } + + if( argumentMap == null ) + return info; + + if( info.isType( TypeInfo.t_type ) && + info.getTypeSymbol().isType( TypeInfo.t_templateParameter ) && + argumentMap.containsKey( info.getTypeSymbol() ) ) + { + TypeInfo newType = new TypeInfo( (TypeInfo) argumentMap.get( info.getTypeSymbol() ) ); + if( info.hasPtrOperators() ) + newType.addPtrOperator( info.getPtrOperators() ); + + return newType; + } + + return info; + } + + static protected List selectTemplateFunctions( Set templates, List arguments ) throws ParserSymbolTableException{ + if( templates == null || templates.size() == 0 ) + return null; + + List instances = new LinkedList(); + + Iterator iter = templates.iterator(); + + while( iter.hasNext() ){ + IParameterizedSymbol fn = (IParameterizedSymbol) iter.next(); + ITemplateSymbol template = (ITemplateSymbol) fn.getContainingSymbol(); + + Map map = deduceTemplateArguments( template, arguments ); + + if( map == null ) + continue; + + Iterator paramIter = template.getParameterList().iterator(); + List instanceArgs = new LinkedList(); + while( paramIter.hasNext() ){ + instanceArgs.add( map.get( paramIter.next() ) ); + } + + IContainerSymbol instance = (IContainerSymbol) template.instantiate( instanceArgs ); + + if( instance != null ){ + instances.add( instance ); + } + } + + return instances; + } + + /** + * @param look + * @param parameters + * @param arguments + * @throws ParserSymbolTableException + */ + static protected ITemplateSymbol selectTemplateOrSpecialization( ITemplateSymbol template, List parameters, List arguments ) throws ParserSymbolTableException { + if( template != null && template instanceof ITemplateSymbol ){ + //primary definition or specialization? + boolean forPrimary = true; + + if( arguments != null ){ + if( !parameters.isEmpty() ){ + if( arguments.size() != parameters.size() ){ + forPrimary = false; + } else { + Iterator pIter = parameters.iterator(); + Iterator aIter = arguments.iterator(); + while( pIter.hasNext() ){ + if( pIter.next() != ((TypeInfo) aIter.next()).getTypeSymbol() ){ + forPrimary = false; + break; + } + } + } + } + } + + ITemplateSymbol primary = (ITemplateSymbol) template; + + if( forPrimary ){ + //make sure parameters match up with found template + if( checkTemplateParameterListsAreEquivalent( primary.getParameterList(), parameters ) ){ + return template; + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateParameter ); + } + } + + //specialization + if( parameters.isEmpty() && !arguments.isEmpty() ){ + ISpecializedSymbol spec = primary.findSpecialization( parameters, arguments ); + + if( spec == null ){ + spec = template.getSymbolTable().newSpecializedSymbol( primary.getName() ); + + Iterator iter = arguments.iterator(); + while( iter.hasNext() ){ + spec.addArgument( (TypeInfo) iter.next() ); + } + + primary.addSpecialization( spec ); + } + + return spec; + } + + //partial specialization + ISpecializedSymbol spec = findPartialSpecialization( template, parameters, arguments ); + + if( spec != null ) + return spec; + + //TODO + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplate ); + + } + return null; + } + + static private boolean checkTemplateParameterListsAreEquivalent( List p1, List p2 ){ + if( p1.size() != p2.size() ){ + return false; + } + + Iterator iter1 = p1.iterator(); + Iterator iter2 = p2.iterator(); + while( iter1.hasNext() ){ + ISymbol param1 = (ISymbol) iter1.next(); + ISymbol param2 = (ISymbol) iter2.next(); + if( param1.getTypeInfo().getTemplateParameterType() != param2.getTypeInfo().getTemplateParameterType() ){ + return false; + } + } + return true; + } + + static private boolean checkTemplateArgumentListsAreEquivalent( List p1, List p2, List a1, List a2 ){ + if( a1.size() != a2.size() || p1.size() != p2.size() ){ + return false; + } + + Map m [] = { new HashMap(), new HashMap() }; + + for( List list = p1; list != null; list = p2 ){ + Iterator i = list.iterator(); + int index = 0; + while( i.hasNext() ){ + m[ ( list == p2 )? 1 : 0 ].put( i.next(), new Integer( index++ ) ); + } + + if( list == p2 ){ + break; + } + } + + Iterator i1 = a1.iterator(); + Iterator i2 = a2.iterator(); + while( i1.hasNext() ){ + TypeInfo t1 = (TypeInfo) i1.next(); + TypeInfo t2 = (TypeInfo) i2.next(); + + if( t1.equals( t2 ) ){ + continue; + } else if( t1.isType( TypeInfo.t_type ) && t2.isType( TypeInfo.t_type ) ) { + ISymbol s1 = t1.getTypeSymbol(), s2 = t2.getTypeSymbol(); + if( m[0].containsKey( s1 ) && m[1].containsKey( s2 ) && m[0].get( s1 ).equals( m[1].get( s2 ) ) ) + continue; + } + + return false; + } + return true; + } + + static private ISpecializedSymbol findPartialSpecialization( ITemplateSymbol template, List parameters, List arguments ){ + + Iterator iter = template.getSpecializations().iterator(); + ISpecializedSymbol spec = null; + while( iter.hasNext() ){ + spec = (ISpecializedSymbol) iter.next(); + + if( ! checkTemplateParameterListsAreEquivalent( spec.getParameterList(), parameters ) ){ + continue; + } + + if( checkTemplateArgumentListsAreEquivalent( spec.getParameterList(), parameters, + spec.getArgumentList(), arguments ) ) + { + return spec; + } + } + return null; + } + + static protected ISymbol translateParameterForDefinition ( ISymbol templatedSymbol, ISymbol param, Map defnMap ){ + if( defnMap == null ){ + return param; + } + + ISymbol mappedParam = param; + while( mappedParam.isTemplateInstance() ){ + mappedParam = mappedParam.getInstantiatedSymbol(); + } + + if( defnMap.containsKey( templatedSymbol ) ){ + Map map = (Map) defnMap.get( templatedSymbol ); + + Iterator i = map.keySet().iterator(); + while( i.hasNext() ){ + ISymbol key = (ISymbol) i.next(); + if( map.get( key ) == mappedParam ){ + return key; + } + } + } + + return param; + } + + /** + * 14.6.1-1 (2) Within the scope of a class template (class template specialization or partial specialization), when + * the name of the template is neither qualified nor followed by <. it is equivalent to the name of the template + * followed by the template-parameters (template-arguments) enclosed in <> + * + * @param symbol + * @return + */ + static protected ISymbol instantiateWithinTemplateScope( IContainerSymbol container, ITemplateSymbol symbol ) + { + if( symbol.getTemplatedSymbol().isType( TypeInfo.t_function ) ){ + return symbol; + } + + IDeferredTemplateInstance instance = null; + + IContainerSymbol containing = container.getContainingSymbol(); + boolean instantiate = false; + while( containing != null ){ + if( containing == symbol ){ + instantiate = true; + break; + } + + containing = containing.getContainingSymbol(); + if( containing != null && !containing.isTemplateMember() || !containing.isType( TypeInfo.t_template ) ){ + containing = null; + } + } + + if( instantiate ){ + if( symbol instanceof ISpecializedSymbol ){ + ISpecializedSymbol spec = (ISpecializedSymbol) symbol; + instance = spec.deferredInstance( spec.getArgumentList() ); + } else { + ITemplateSymbol template = (ITemplateSymbol) symbol; + Iterator iter = template.getParameterList().iterator(); + List args = new LinkedList(); + while( iter.hasNext() ){ + args.add( new TypeInfo( TypeInfo.t_type, 0, (ISymbol) iter.next() ) ); + } + + instance = template.deferredInstance( args ); + } + } + + return ( instance != null ) ? instance : (ISymbol) symbol; + } + + static protected boolean alreadyHasTemplateParameter( IContainerSymbol container, String name ){ + while( container != null ){ + if( container instanceof ITemplateSymbol ){ + ITemplateSymbol template = (ITemplateSymbol) container; + if( template.getParameterMap().containsKey( name ) ){ + return true; + } + } + container = container.getContainingSymbol(); + } + return false; + } + + static protected boolean canAddTemplate( IContainerSymbol containing, ITemplateSymbol template ){ + //14-2 A template-declaration can appear only as a namespace scope or class scope declaration + if( !containing.isType( TypeInfo.t_namespace ) && !containing.isType( TypeInfo.t_class, TypeInfo.t_union ) ){ + return false; + } + + //14.5.2-3 A member function template shall not be virtual + if( containing.isTemplateMember() && containing.getContainingSymbol().isType( TypeInfo.t_template ) ){ + ISymbol symbol = template.getTemplatedSymbol(); + if( symbol != null && symbol.isType( TypeInfo.t_function ) && symbol.getTypeInfo().checkBit( TypeInfo.isVirtual ) ){ + return false; + } + } + + return true; + } + +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java new file mode 100644 index 00000000000..50b33f8510d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateFactory.java @@ -0,0 +1,163 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.cdt.internal.core.parser.pst.ParserSymbolTable.LookupData; + +/** + * @author aniefer + */ +public class TemplateFactory implements ITemplateFactory { + + protected TemplateFactory( ITemplateSymbol primary, List params ){ + templatesList = new LinkedList(); + templatesList.add( primary ); + + parametersList = new LinkedList(); + parametersList.add( new LinkedList( params ) ); + } + + protected TemplateFactory( List templates, List params ){ + templatesList = templates; + parametersList = params; + } + + public ITemplateFactory lookupTemplateForMemberDefinition( String name, List parameters, List arguments ) throws ParserSymbolTableException{ + if( templatesList == null || templatesList.isEmpty() ){ + return null; + } + + ITemplateSymbol template = (ITemplateSymbol) templatesList.get( 0 ); + IContainerSymbol symbol = template.getTemplatedSymbol(); + LookupData data = new LookupData( name, TypeInfo.t_any ); //, null ); + + ParserSymbolTable.lookup( data, symbol ); + + ISymbol look = ParserSymbolTable.resolveAmbiguities( data ); + + if( look.getContainingSymbol() instanceof ITemplateSymbol ){ + template = TemplateEngine.selectTemplateOrSpecialization( (ITemplateSymbol) look.getContainingSymbol(), parameters, arguments ); + if( template != null ){ + List newTemplatesList = new LinkedList( templatesList ); + List newParamsList = new LinkedList( parametersList ); + + newTemplatesList.add( template ); + newParamsList.add( new LinkedList( parameters ) ); + + return new TemplateFactory( newTemplatesList, newParamsList ); + } + } + + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#addSymbol(org.eclipse.cdt.internal.core.parser.pst.ISymbol) + */ + public void addSymbol( ISymbol symbol ) throws ParserSymbolTableException { + Iterator templatesIter = getTemplatesList().iterator(); + Iterator parametersIter = getParametersList().iterator(); + + while( templatesIter.hasNext() ){ + Map defnMap = new HashMap(); + + ITemplateSymbol template = (ITemplateSymbol) templatesIter.next(); + + Iterator tempIter = template.getParameterList().iterator(); + + if( !parametersIter.hasNext() ){ + throw new ParserSymbolTableError( ParserSymbolTableError.r_InternalError ); + } + + List params = (List) parametersIter.next(); + Iterator iter = params.iterator(); + + while( iter.hasNext() ){ + ISymbol param = (ISymbol) iter.next(); + ISymbol tempParam = (ISymbol) tempIter.next(); + defnMap.put( param, tempParam ); + } + + template.getDefinitionParameterMap().put( symbol, defnMap ); + } + + ITemplateSymbol template = (ITemplateSymbol) getTemplatesList().get( getTemplatesList().size() - 1 ); + IContainerSymbol container = (IContainerSymbol) template.getTemplatedSymbol(); + + if( container.isForwardDeclaration() && container.getTypeSymbol() == symbol ){ + template.addSymbol( symbol ); + } else { + container.addSymbol( symbol ); + } + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#lookupMemberForDefinition(java.lang.String) + */ + public ISymbol lookupMemberForDefinition(String name) throws ParserSymbolTableException { + Set keys = getPrimaryTemplate().getContainedSymbols().keySet(); + IContainerSymbol symbol = (IContainerSymbol) getPrimaryTemplate().getContainedSymbols().get( keys.iterator().next() ); + + return (ISymbol) symbol.lookupMemberForDefinition( name ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#lookupMemberFunctionForDefinition(java.lang.String, java.util.List) + */ + public IParameterizedSymbol lookupMemberFunctionForDefinition( String name, List params) throws ParserSymbolTableException { + Set keys = getPrimaryTemplate().getContainedSymbols().keySet(); + IContainerSymbol symbol = (IContainerSymbol) getPrimaryTemplate().getContainedSymbols().get( keys.iterator().next() ); + + return (IParameterizedSymbol) symbol.lookupMethodForDefinition( name, params ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.ITemplateFactory#getPrimaryTemplate() + */ + public ITemplateSymbol getPrimaryTemplate() { + return (ITemplateSymbol) templatesList.get( 0 ); + } + + public ISymbol lookupParam( String name ) throws ParserSymbolTableException{ + Iterator iter = getParametersList().iterator(); + + while( iter.hasNext() ){ + List list = (List) iter.next(); + Iterator params = list.iterator(); + while( params.hasNext() ){ + ISymbol p = (ISymbol) params.next(); + if( p.getName().equals( name ) ){ + return p; + } + } + } + + return getPrimaryTemplate().lookup( name ); + } + + + protected List getTemplatesList() { + return templatesList; + } + protected List getParametersList() { + return parametersList; + } + + private List templatesList; + private List parametersList; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateInstance.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateInstance.java deleted file mode 100644 index 8243af37925..00000000000 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateInstance.java +++ /dev/null @@ -1,135 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2003 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Common Public License v0.5 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/cpl-v05.html - * - * Contributors: - * IBM Corp. - Rational Software - initial implementation - ******************************************************************************/ -/* - * Created on Nov 6, 2003 - */ -package org.eclipse.cdt.internal.core.parser.pst; - -import java.util.Iterator; -import java.util.Map; - - -public class TemplateInstance extends BasicSymbol -{ - //TODO ANDREW - this field is not read, is this a work in progress? - //private final ParserSymbolTable _table; - - protected TemplateInstance( ParserSymbolTable table, ISymbol symbol, Map argMap ){ - super(table, ParserSymbolTable.EMPTY_NAME ); - //this._table = table; - _instantiatedSymbol = symbol; - symbol.setTemplateInstance( this ); - _argumentMap = argMap; - } - - public boolean equals( Object t ){ - if( t == null || !( t instanceof TemplateInstance ) ){ - return false; - } - - TemplateInstance instance = (TemplateInstance) t; - - if( _instantiatedSymbol != instance._instantiatedSymbol ){ - return false; - } - - //check arg map - Iterator iter1 = _argumentMap.keySet().iterator(); - Iterator iter2 = instance._argumentMap.keySet().iterator(); - int size = _argumentMap.size(); - int size2 = instance._argumentMap.size(); - ISymbol t1 = null, t2 = null; - if( size == size2 ){ - for( int i = size; i > 0; i-- ){ - t1 = (ISymbol)iter1.next(); - t2 = (ISymbol)iter2.next(); - if( t1 != t2 || !_argumentMap.get(t1).equals( instance._argumentMap.get(t2) ) ){ - return false; - } - } - } - - return true; - } - - public ISymbol getInstantiatedSymbol(){ - _instantiatedSymbol.setTemplateInstance( this ); - return _instantiatedSymbol; - } - - public TypeInfo.eType getType(){ - ISymbol symbol = _instantiatedSymbol; - TypeInfo.eType returnType = _instantiatedSymbol.getType(); - if( returnType == TypeInfo.t_type ){ - symbol = symbol.getTypeSymbol(); - TypeInfo info = null; - while( symbol != null && symbol.getType() == TypeInfo.t_undef && symbol.getContainingSymbol().getType() == TypeInfo.t_template ){ - info = (TypeInfo) _argumentMap.get( symbol ); - if( !info.isType( TypeInfo.t_type ) ){ - break; - } - symbol = info.getTypeSymbol(); - } - - return ( info != null ) ? info.getType() : TypeInfo.t_type; - } - - return returnType; - } - - public boolean isType( TypeInfo.eType type ){ - return ( type == TypeInfo.t_any || getType() == type ); - } - - public boolean isType( TypeInfo.eType type, TypeInfo.eType upperType ){ - if( type == TypeInfo.t_any ) - return true; - - if( upperType == TypeInfo.t_undef ){ - return ( getType() == type ); - } else { - return ( getType().compareTo( type ) >= 0 && getType().compareTo( upperType ) <= 0 ); - } - } - - public ISymbol getTypeSymbol(){ - ISymbol symbol = _instantiatedSymbol.getTypeSymbol(); - if( symbol != null && symbol.getType() == TypeInfo.t_undef && - symbol.getContainingSymbol().getType() == TypeInfo.t_template ) - { - TypeInfo info = (TypeInfo) _argumentMap.get( symbol ); - return ( info != null ) ? info.getTypeSymbol() : null; - } - - return symbol; - } - - public TypeInfo getTypeInfo(){ - ISymbol symbol = _instantiatedSymbol.getTypeSymbol(); - if( symbol != null && symbol.getType() == TypeInfo.t_undef && - symbol.getContainingSymbol().getType() == TypeInfo.t_template ) - { - TypeInfo info = (TypeInfo) _argumentMap.get( symbol ); - return info; - } - - return _instantiatedSymbol.getTypeInfo(); - } - - public Map getArgumentMap(){ - return _argumentMap; - } - - - private ISymbol _instantiatedSymbol; - //private LinkedList _arguments; - private Map _argumentMap; -} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java new file mode 100644 index 00000000000..afaad47de47 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TemplateSymbol.java @@ -0,0 +1,318 @@ +/********************************************************************** + * Copyright (c) 2004 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * IBM Rational Software - Initial API and implementation +***********************************************************************/ +package org.eclipse.cdt.internal.core.parser.pst; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.eclipse.cdt.internal.core.parser.pst.TypeInfo.PtrOp; + +/** + * @author aniefer + * + * To change the template for this generated type comment go to + * Window - Preferences - Java - Code Generation - Code and Comments + */ +public class TemplateSymbol extends ParameterizedSymbol implements ITemplateSymbol { + + protected TemplateSymbol ( ParserSymbolTable table, String name ){ + super( table, name, TypeInfo.t_template ); + } + + protected TemplateSymbol( ParserSymbolTable table, String name, ISymbolASTExtension obj ){ + super( table, name, obj ); + } + + public Object clone(){ + TemplateSymbol copy = (TemplateSymbol)super.clone(); + + //copy._specializations = ( _specializations != null ) ? (LinkedList) _specializations.clone() : null; + + copy._defnParameterMap = ( _defnParameterMap != null ) ? (HashMap) _defnParameterMap.clone() : null; + copy._instantiations = ( _instantiations != null ) ? (HashMap) _instantiations.clone() : null; + + + return copy; + } + + public IContainerSymbol getTemplatedSymbol(){ + Iterator iter = getContentsIterator(); + if( iter.hasNext() ){ + IContainerSymbol contained = (IContainerSymbol) iter.next(); + if( contained.isForwardDeclaration() && contained.getTypeSymbol() != null ){ + ISymbol symbol = contained.getTypeSymbol(); + if( symbol.getContainingSymbol() == this ) + return (IContainerSymbol) symbol; + } + return contained; + } + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#instantiate(java.util.List) + */ + public ISymbol instantiate( List arguments ) throws ParserSymbolTableException{ + if( getType() != TypeInfo.t_template && + ( getType() != TypeInfo.t_templateParameter || + getTypeInfo().getTemplateParameterType() != TypeInfo.t_template ) ) + { + return null; + } + + ITemplateSymbol template = TemplateEngine.matchTemplatePartialSpecialization( this, arguments ); + + if( template != null && template instanceof ISpecializedSymbol ){ + return template.instantiate( arguments ); + } + + if( template == null ){ + template = this; + } + + List paramList = template.getParameterList(); + int numParams = ( paramList != null ) ? paramList.size() : 0; + + if( numParams == 0 ){ + return null; + } + + HashMap map = new HashMap(); + Iterator paramIter = paramList.iterator(); + Iterator argIter = arguments.iterator(); + + ISymbol param = null; + TypeInfo arg = null; + + List actualArgs = new LinkedList(); + + ISymbol templatedSymbol = template.getTemplatedSymbol(); + while( templatedSymbol != null && templatedSymbol.isTemplateInstance() ){ + templatedSymbol = templatedSymbol.getInstantiatedSymbol(); + } + + for( int i = 0; i < numParams; i++ ){ + param = (ISymbol) paramIter.next(); + + param = TemplateEngine.translateParameterForDefinition ( templatedSymbol, param, getDefinitionParameterMap() ); + + if( argIter.hasNext() ){ + arg = (TypeInfo) argIter.next(); + + //If the argument is a template parameter, we can't instantiate yet, defer for later + if( arg.isType( TypeInfo.t_type ) && arg.getTypeSymbol().isType( TypeInfo.t_templateParameter ) ){ + return deferredInstance( arguments ); + } + } else { + Object obj = param.getTypeInfo().getDefault(); + if( obj != null && obj instanceof TypeInfo ){ + arg = (TypeInfo) obj; + if( arg.isType( TypeInfo.t_type ) && arg.getTypeSymbol().isType( TypeInfo.t_templateParameter ) ){ + if( map.containsKey( arg.getTypeSymbol() ) ){ + arg = (TypeInfo) map.get( arg.getTypeSymbol() ); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateArgument ); + } + } + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateArgument ); + } + } + + if( TemplateEngine.matchTemplateParameterAndArgument( param, arg ) ){ + map.put( param, arg ); + actualArgs.add( arg ); + } else { + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateArgument ); + } + } + + IContainerSymbol instance = findInstantiation( actualArgs ); + if( instance != null ){ + return instance; + } else { + if( template.isType( TypeInfo.t_templateParameter ) ){ + //template template parameter. must defer instantiation + return deferredInstance( arguments ); + } + + IContainerSymbol symbol = template.getTemplatedSymbol(); + instance = (IContainerSymbol) symbol.instantiate( template, map ); + addInstantiation( instance, actualArgs ); + return instance; + } + } + + + public void addParameter( ISymbol param ) { + throw new ParserSymbolTableError( ParserSymbolTableError.r_OperationNotSupported ); + } + + public void addTemplateParameter( ISymbol param ) throws ParserSymbolTableException { + if( isType( TypeInfo.t_template ) ){ + if( !isAllowableTemplateParameter( param ) ){ + throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTemplateParameter ); + } + modifyTemplateParameter( param ); + } + + super.addParameter( param ); + } + + private boolean isAllowableTemplateParameter( ISymbol param ) { + if( !param.isType( TypeInfo.t_templateParameter ) ) + return false; + + if( param.getName().equals( getName() ) ){ + return false; + } + + if( param.getTypeInfo().getTemplateParameterType() != TypeInfo.t_typeName && + param.getTypeInfo().getTemplateParameterType() != TypeInfo.t_template ) + { + if( param.isType( TypeInfo.t_bool, TypeInfo.t_int ) || + param.isType( TypeInfo.t_enumerator ) ) + { + return true; + } + + //a non-tpye template parameter shall have one of the following: + //integral or enumeration type + //pointer to object or pointer to function + //reference to object or reference to function + //pointer to member + + //A non-type template-parameter shall not be declared to have floating point, class or void type + if( param.isType( TypeInfo.t_float ) || + param.isType( TypeInfo.t_double )|| + param.isType( TypeInfo.t_class ) || + param.isType( TypeInfo.t_void ) ) + { + return false; + } + } + return true; + } + + private void modifyTemplateParameter( ISymbol param ){ + List ptrs = param.getPtrOperators(); + if( ptrs.size() > 0 ){ + PtrOp op = (PtrOp) ptrs.get( 0 ); + if( op.getType() == PtrOp.t_array ){ + op.setType( PtrOp.t_pointer ); + } + } else if ( param.isType( TypeInfo.t_type ) && param.getTypeSymbol().isType( TypeInfo.t_function ) ){ + param.addPtrOperator( new PtrOp( PtrOp.t_pointer ) ); + } + } + + + + + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#hasSpecializations() + */ + public boolean hasSpecializations(){ + return ( _specializations != null && !_specializations.isEmpty() ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#addSpecialization(org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol) + */ + public void addSpecialization( ISpecializedSymbol spec ){ + List specializationList = getSpecializations(); + specializationList.add( spec ); + + spec.setContainingSymbol( getContainingSymbol() ); + spec.setPrimaryTemplate( this ); + } + + /* (non-Javadoc) + * @see org.eclipse.cdt.internal.core.parser.pst.IParameterizedSymbol#getSpecializations() + */ + public List getSpecializations() { + if( _specializations == null ){ + _specializations = new LinkedList(); + } + return _specializations; + } + + public void addInstantiation( IContainerSymbol instance, List args ){ + List key = new LinkedList( args ); + if( _instantiations == null ){ + _instantiations = new HashMap(); + } + _instantiations.put( key, instance ); + } + + public IContainerSymbol findInstantiation( List arguments ){ + if( _instantiations == null ){ + return null; + } + + //TODO: we could optimize this by doing something other than a linear search. + Iterator iter = _instantiations.keySet().iterator(); + List args = null; + while( iter.hasNext() ){ + args = (List) iter.next(); + + if( args.equals( arguments ) ){ + return (IContainerSymbol) _instantiations.get( args ); + } + } + return null; + } + + public List findArgumentsFor( IContainerSymbol instance ){ + if( instance == null || !instance.isTemplateInstance() ) + return null; + + ITemplateSymbol template = (ITemplateSymbol) instance.getInstantiatedSymbol().getContainingSymbol(); + if( template != this ) + return null; + + Iterator iter = _instantiations.keySet().iterator(); + while( iter.hasNext() ){ + List args = (List) iter.next(); + if( _instantiations.get( args ) == instance ){ + return args; + } + } + + return null; + } + + public Map getDefinitionParameterMap(){ + if( _defnParameterMap == null ){ + _defnParameterMap = new HashMap(); + } + return _defnParameterMap; + } + + public IDeferredTemplateInstance deferredInstance( List args ){ + return new DeferredTemplateInstance( getSymbolTable(), this, args ); + } + + public ISpecializedSymbol findSpecialization(List parameters, List arguments) { + // TODO Auto-generated method stub + return null; + } + + + private LinkedList _specializations; //template specializations + private HashMap _defnParameterMap; //members could be defined with different template parameter names + private HashMap _instantiations; + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java index 3ec8062a769..992dfd3e147 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/TypeInfo.java @@ -1,5 +1,5 @@ /********************************************************************** - * Copyright (c) 2002,2003 Rational Software Corporation and others. + * Copyright (c) 2002,2003, 2004 Rational Software Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v0.5 * which accompanies this distribution, and is available at @@ -67,6 +67,7 @@ public class TypeInfo { _typeDeclaration = info._typeDeclaration; _ptrOperators = ( info._ptrOperators == null ) ? null : (LinkedList)info._ptrOperators.clone(); _hasDefaultValue = info._hasDefaultValue; + _defaultValue = info._defaultValue; } public static final int typeMask = 0x001f; @@ -117,6 +118,8 @@ public class TypeInfo { public static final TypeInfo.eType t_template = new TypeInfo.eType( 19 ); public static final TypeInfo.eType t_asm = new TypeInfo.eType( 20 ); public static final TypeInfo.eType t_linkage = new TypeInfo.eType( 21 ); + public static final TypeInfo.eType t_templateParameter = new TypeInfo.eType( 22 ); + public static final TypeInfo.eType t_typeName = new TypeInfo.eType( 23 ); //public static final eType t_templateParameter = new eType( 18 ); @@ -282,6 +285,14 @@ public class TypeInfo { _typeInfo = typeInfo; } + public eType getTemplateParameterType(){ + return _templateParameterType; + } + + public void setTemplateParameterType( eType type ){ + _templateParameterType = type; + } + /** * * @param type @@ -476,19 +487,25 @@ public class TypeInfo { boolean result = ( _typeInfo == type._typeInfo ); result &= ( _type == type._type ); - if( _typeDeclaration instanceof TemplateInstance ){ - result &= _typeDeclaration.equals( type._typeDeclaration ); + if( _typeDeclaration != null && type._typeDeclaration != null && + _typeDeclaration.isType( TypeInfo.t__Bool, TypeInfo.t_void ) && + type._typeDeclaration.isType( TypeInfo.t__Bool, TypeInfo.t_void ) ) + { + //if typeDeclaration is a basic type, then only need the types the same + result &= ( _typeDeclaration.getType() == type._typeDeclaration.getType() ); + } else if( _typeDeclaration != null && type._typeDeclaration != null && + _typeDeclaration.isType( TypeInfo.t_function ) && + type._typeDeclaration.isType( TypeInfo.t_function ) ) + { + //function pointers... functions must have same parameter lists and return types + IParameterizedSymbol f1 = (IParameterizedSymbol) _typeDeclaration; + IParameterizedSymbol f2 = (IParameterizedSymbol) type._typeDeclaration; + + result &= f1.hasSameParameters( f2 ); + result &= f1.getReturnType().getTypeInfo().equals( f2.getReturnType().getTypeInfo() ); } else { - if( _typeDeclaration != null && type._typeDeclaration != null && - _typeDeclaration.isType( TypeInfo.t__Bool, TypeInfo.t_void ) && - type._typeDeclaration.isType( TypeInfo.t__Bool, TypeInfo.t_void ) ) - { - //if typeDeclaration is a basic type, then only need the types the same - result &= ( _typeDeclaration.getType() == type._typeDeclaration.getType() ); - } else { - //otherwise, its a user defined type, need the decls the same - result &= ( _typeDeclaration == type._typeDeclaration ); - } + //otherwise, its a user defined type, need the decls the same + result &= ( _typeDeclaration == type._typeDeclaration ); } int size1 = (_ptrOperators == null) ? 0 : _ptrOperators.size(); @@ -524,7 +541,8 @@ public class TypeInfo { } private int _typeInfo = 0; - private TypeInfo.eType _type = TypeInfo.t_undef; + private eType _type = TypeInfo.t_undef; + private eType _templateParameterType = t_typeName; private ISymbol _typeDeclaration; private boolean _hasDefaultValue = false;