1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Fix template scoping

- helps with nested templates & template specializations
- fxes bug 90686
This commit is contained in:
Andrew Niefer 2005-05-09 16:15:14 +00:00
parent ecd91d8fe3
commit ce4decd0a0
11 changed files with 563 additions and 155 deletions

View file

@ -560,37 +560,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
}
}
/**
[--Start Example(CPP 14.6.1-6):
namespace N {
class C { };
template<class T> class B {
void f(T);
};
}
template<class C> void N::B<C>::f(C) {
C b; // C is the template parameter, not N::C
}
--End Example]
*/
public void test14_6_1s6() { // TODO raised bug 90686
StringBuffer buffer = new StringBuffer();
buffer.append("namespace N {\n"); //$NON-NLS-1$
buffer.append("int C;\n"); //$NON-NLS-1$
buffer.append("template<class T> class B {\n"); //$NON-NLS-1$
buffer.append("void f(T);\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
buffer.append("template<class C> void N::B<C>::f(C) {\n"); //$NON-NLS-1$
buffer.append("C b; // C is the template parameter, not N::C\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
try {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
assertTrue(false);
} catch (Exception e) {
}
}
/**
[--Start Example(CPP 14.6.2-3):
typedef double A;
@ -709,55 +678,6 @@ public class AST2CPPSpecFailingTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 1);
}
/**
[--Start Example(CPP 14.7.3-16):
template<class T> struct A {
void f(T);
template<class X> void g(T,X);
void h(T) { }
};
// specialization
template<> void A<int>::f(int);
// out of class member template definition
template<class T> template<class X> void A<T>::g(T,X) { }
// member template partial specialization
template<> template<class X> void A<int>::g(int,X);
// member template specialization
template<> template<>
void A<int>::g(int,char); // X deduced as char
template<> template<>
void A<int>::g<char>(int,char); // X specified as char
// member specialization even if defined in class definition
template<> void A<int>::h(int) { }
--End Example]
*/
public void test14_7_3s16() { // TODO similar bug already
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> struct A {\n"); //$NON-NLS-1$
buffer.append("void f(T);\n"); //$NON-NLS-1$
buffer.append("template<class X> void g(T,X);\n"); //$NON-NLS-1$
buffer.append("void h(T) { }\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("// specialization\n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::f(int);\n"); //$NON-NLS-1$
buffer.append("// out of class member template definition\n"); //$NON-NLS-1$
buffer.append("template<class T> template<class X> void A<T>::g(T,X) { }\n"); //$NON-NLS-1$
buffer.append("// member template partial specialization\n"); //$NON-NLS-1$
buffer.append("template<> template<class X> void A<int>::g(int,X);\n"); //$NON-NLS-1$
buffer.append("// member template specialization\n"); //$NON-NLS-1$
buffer.append("template<> template<>\n"); //$NON-NLS-1$
buffer.append("void A<int>::g(int,char); // X deduced as char\n"); //$NON-NLS-1$
buffer.append("template<> template<>\n"); //$NON-NLS-1$
buffer.append("void A<int>::g<char>(int,char); // X specified as char\n"); //$NON-NLS-1$
buffer.append("// member specialization even if defined in class definition\n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::h(int) { }\n"); //$NON-NLS-1$
try {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
assertTrue(false);
} catch (Exception e) {
}
}
/**
[--Start Example(CPP 14.8.2-2b):
template <class T> int f(typename T::B*);

View file

@ -9767,6 +9767,34 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/**
[--Start Example(CPP 14.6.1-6):
namespace N {
class C { };
template<class T> class B {
void f(T);
};
}
template<class C> void N::B<C>::f(C) {
C b; // C is the template parameter, not N::C
}
--End Example]
*/
public void test14_6_1s6() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("namespace N {\n"); //$NON-NLS-1$
buffer.append("int C;\n"); //$NON-NLS-1$
buffer.append("template<class T> class B {\n"); //$NON-NLS-1$
buffer.append("void f(T);\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
buffer.append("template<class C> void N::B<C>::f(C) {\n"); //$NON-NLS-1$
buffer.append("C b; // C is the template parameter, not N::C\n"); //$NON-NLS-1$
buffer.append("}\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/**
[--Start Example(CPP 14.6.1-7):
struct A {
@ -10427,6 +10455,51 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/**
[--Start Example(CPP 14.7.3-16):
template<class T> struct A {
void f(T);
template<class X> void g(T,X);
void h(T) { }
};
// specialization
template<> void A<int>::f(int);
// out of class member template definition
template<class T> template<class X> void A<T>::g(T,X) { }
// member template partial specialization
template<> template<class X> void A<int>::g(int,X);
// member template specialization
template<> template<>
void A<int>::g(int,char); // X deduced as char
template<> template<>
void A<int>::g<char>(int,char); // X specified as char
// member specialization even if defined in class definition
template<> void A<int>::h(int) { }
--End Example]
*/
public void test14_7_3s16() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> struct A {\n"); //$NON-NLS-1$
buffer.append("void f(T);\n"); //$NON-NLS-1$
buffer.append("template<class X> void g(T,X);\n"); //$NON-NLS-1$
buffer.append("void h(T) { }\n"); //$NON-NLS-1$
buffer.append("};\n"); //$NON-NLS-1$
buffer.append("// specialization\n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::f(int);\n"); //$NON-NLS-1$
buffer.append("// out of class member template definition\n"); //$NON-NLS-1$
buffer.append("template<class T> template<class X> void A<T>::g(T,X) { }\n"); //$NON-NLS-1$
buffer.append("// member template partial specialization\n"); //$NON-NLS-1$
buffer.append("template<> template<class X> void A<int>::g(int,X);\n"); //$NON-NLS-1$
buffer.append("// member template specialization\n"); //$NON-NLS-1$
buffer.append("template<> template<>\n"); //$NON-NLS-1$
buffer.append("void A<int>::g(int,char); // X deduced as char\n"); //$NON-NLS-1$
buffer.append("template<> template<>\n"); //$NON-NLS-1$
buffer.append("void A<int>::g<char>(int,char); // X specified as char\n"); //$NON-NLS-1$
buffer.append("// member specialization even if defined in class definition\n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::h(int) { }\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.CPP, true, 0);
}
/**
[--Start Example(CPP 14.7.3-18):
template<class T1> class A {

View file

@ -1174,6 +1174,79 @@ public class AST2TemplateTests extends AST2BaseTest {
assertTrue( x4 instanceof ICPPSpecialization );
assertEquals( ((ICPPSpecialization)x4).getSpecializedBinding(), x2 );
}
public void _testNestedTypeSpecializations() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template <class T> class A { \n"); //$NON-NLS-1$
buffer.append(" typedef T _T; \n"); //$NON-NLS-1$
buffer.append(" _T t; \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("void f() { \n"); //$NON-NLS-1$
buffer.append(" A<int> a; \n"); //$NON-NLS-1$
buffer.append(" a.t; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
ITypedef _T = (ITypedef) col.getName(3).resolveBinding();
assertSame( _T.getType(), T );
ICPPField t = (ICPPField) col.getName(5).resolveBinding();
assertSame( t.getType(), _T );
ICPPField t2 = (ICPPField) col.getName(11).resolveBinding();
assertTrue( t2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)t2).getSpecializedBinding(), t );
IType type = t2.getType();
assertTrue( type instanceof ITypedef );
assertTrue( type instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)type).getSpecializedBinding(), _T );
type = ((ITypedef)type).getType();
assertTrue( type instanceof IBasicType );
assertEquals( ((IBasicType)type).getType(), IBasicType.t_int );
}
public void _testNestedClassTypeSpecializations() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template <class T> class A { \n"); //$NON-NLS-1$
buffer.append(" class B { T t; }; \n"); //$NON-NLS-1$
buffer.append(" B b; \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("void f() { \n"); //$NON-NLS-1$
buffer.append(" A<int> a; \n"); //$NON-NLS-1$
buffer.append(" a.b.t; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
ICPPClassType B = (ICPPClassType) col.getName(2).resolveBinding();
ICPPField t = (ICPPField) col.getName(4).resolveBinding();
assertSame( t.getType(), T );
ICPPField b = (ICPPField) col.getName(6).resolveBinding();
assertSame( b.getType(), B );
ICPPField b2 = (ICPPField) col.getName(12).resolveBinding();
ICPPField t2 = (ICPPField) col.getName(13).resolveBinding();
assertTrue( b2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)b2).getSpecializedBinding(), b );
IType type = b2.getType();
assertTrue( type instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)type).getSpecializedBinding(), B );
assertTrue( t2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)t2).getSpecializedBinding(), t );
assertTrue( t2.getType() instanceof IBasicType );
assertEquals( ((IBasicType)t2.getType()).getType(), IBasicType.t_int );
}
public void testTemplateParameterQualifiedType_1() throws Exception {
StringBuffer buffer = new StringBuffer();
@ -1234,5 +1307,170 @@ public class AST2TemplateTests extends AST2BaseTest {
assertSame( t, B );
}
public void testTemplateScopes() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template <class T> class A { \n"); //$NON-NLS-1$
buffer.append(" A<T> a; \n"); //$NON-NLS-1$
buffer.append(" void f(); \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("template <class U> void A<U>::f(){ \n"); //$NON-NLS-1$
buffer.append(" U u; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
ICPPClassTemplate A = (ICPPClassTemplate) col.getName(1).resolveBinding();
ICPPClassType A2 = (ICPPClassType) col.getName(2).resolveBinding();
ICPPTemplateParameter U = (ICPPTemplateParameter) col.getName(7).resolveBinding();
assertSame( U, T );
ICPPClassType A3 = (ICPPClassType) col.getName(9).resolveBinding();
assertTrue( A3 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance) A3).getTemplateDefinition(), A );
assertSame( A2, A3 );
ICPPTemplateParameter U2 = (ICPPTemplateParameter) col.getName(13).resolveBinding();
assertSame( U, U2 );
assertSame( T, U );
}
public void testTemplateScopes_2() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("class A { \n"); //$NON-NLS-1$
buffer.append(" template < class T > void f(T); \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("template <class U> void A::f<>(U){} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPClassType A = (ICPPClassType) col.getName(0).resolveBinding();
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(1).resolveBinding();
ICPPFunctionTemplate f1 = (ICPPFunctionTemplate) col.getName(2).resolveBinding();
ICPPTemplateParameter T2 = (ICPPTemplateParameter) col.getName(3).resolveBinding();
assertSame( T, T2 );
ICPPTemplateParameter U = (ICPPTemplateParameter) col.getName(5).resolveBinding();
assertSame( T, U );
ICPPClassType A2 = (ICPPClassType) col.getName(7).resolveBinding();
assertSame( A, A2 );
ICPPMethod f2 = (ICPPMethod) col.getName(8).resolveBinding();
IBinding U2 = col.getName(10).resolveBinding();
assertSame( U, U2 );
assertTrue( f2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)f2).getSpecializedBinding(), f1 );
}
public void test14_7_3s16() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("template<class T> struct A { \n"); //$NON-NLS-1$
buffer.append(" void f(T); \n"); //$NON-NLS-1$
buffer.append(" template<class X> void g(T,X); \n"); //$NON-NLS-1$
buffer.append(" void h(T) { } \n"); //$NON-NLS-1$
buffer.append("}; \n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::f(int); \n"); //$NON-NLS-1$
buffer.append("template<class T> template<class X> void A<T>::g(T,X) { } \n"); //$NON-NLS-1$
buffer.append("template<> template<class X> void A<int>::g(int,X); \n"); //$NON-NLS-1$
buffer.append("template<> template<> void A<int>::g(int,char); \n"); //$NON-NLS-1$
buffer.append("template<> template<> void A<int>::g<char>(int,char); \n"); //$NON-NLS-1$
buffer.append("template<> void A<int>::h(int) { } \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(0).resolveBinding();
ICPPClassType A = (ICPPClassType) col.getName(1).resolveBinding();
ICPPMethod f = (ICPPMethod) col.getName(2).resolveBinding();
ICPPTemplateParameter T2 = (ICPPTemplateParameter) col.getName(3).resolveBinding();
assertSame( T, T2 );
ICPPTemplateParameter X = (ICPPTemplateParameter) col.getName(5).resolveBinding();
ICPPFunctionTemplate g = (ICPPFunctionTemplate) col.getName(6).resolveBinding();
ICPPTemplateParameter T3 = (ICPPTemplateParameter) col.getName(7).resolveBinding();
assertSame( T, T3 );
ICPPTemplateParameter X2 = (ICPPTemplateParameter) col.getName(9).resolveBinding();
assertSame( X, X2 );
ICPPMethod h = (ICPPMethod) col.getName(11).resolveBinding();
ICPPTemplateParameter T4 = (ICPPTemplateParameter) col.getName(12).resolveBinding();
assertSame( T, T4 );
ICPPClassType A2 = (ICPPClassType) col.getName(15).resolveBinding();
assertTrue( A2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A2).getTemplateDefinition(), A );
ICPPMethod f2 = (ICPPMethod) col.getName(17).resolveBinding();
assertTrue( f2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)f2).getSpecializedBinding(), f );
ICPPTemplateParameter TR = (ICPPTemplateParameter) col.getName(19).resolveBinding();
assertSame( T, TR );
ICPPTemplateParameter XR = (ICPPTemplateParameter) col.getName(20).resolveBinding();
assertSame( X, XR );
ICPPClassType A3 = (ICPPClassType) col.getName(22).resolveBinding();
assertTrue( A3 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)A3).getTemplateDefinition(), A );
assertNotSame( A2, A3 );
ICPPMethod g2 = (ICPPMethod) col.getName(25).resolveBinding();
assertSame( g2, g );
TR = (ICPPTemplateParameter) col.getName(26).resolveBinding();
assertSame( T, TR );
XR = (ICPPTemplateParameter) col.getName(28).resolveBinding();
assertSame( X, XR );
assertSame( col.getName(32).resolveBinding(), A2 );
assertSame( col.getName(39).resolveBinding(), A2 );
assertSame( col.getName(45).resolveBinding(), A2 );
assertSame( col.getName(52).resolveBinding(), A2 );
ICPPMethod h2 = (ICPPMethod) col.getName(54).resolveBinding();
assertTrue( h2 instanceof ICPPSpecialization );
assertSame( ((ICPPSpecialization)h2).getSpecializedBinding(), h );
}
public void test14_6_1s6() throws Exception {
StringBuffer buffer = new StringBuffer();
buffer.append("namespace N { \n"); //$NON-NLS-1$
buffer.append(" int C; \n"); //$NON-NLS-1$
buffer.append(" template<class T> class B { \n"); //$NON-NLS-1$
buffer.append(" void f(T); \n"); //$NON-NLS-1$
buffer.append(" }; \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
buffer.append("template<class C> void N::B<C>::f(C) { \n"); //$NON-NLS-1$
buffer.append(" C b; // C is the template parameter, not N::C \n"); //$NON-NLS-1$
buffer.append("} \n"); //$NON-NLS-1$
IASTTranslationUnit tu = parse( buffer.toString(), ParserLanguage.CPP );
CPPNameCollector col = new CPPNameCollector();
tu.accept( col );
ICPPTemplateParameter T = (ICPPTemplateParameter) col.getName(2).resolveBinding();
ICPPClassTemplate B = (ICPPClassTemplate) col.getName(3).resolveBinding();
ICPPMethod f = (ICPPMethod) col.getName(4).resolveBinding();
ICPPTemplateParameter TR = (ICPPTemplateParameter) col.getName(5).resolveBinding();
assertSame( T, TR );
ICPPTemplateParameter C = (ICPPTemplateParameter) col.getName(7).resolveBinding();
assertSame( C, T );
ICPPClassType B2 = (ICPPClassType) col.getName(10).resolveBinding();
assertTrue( B2 instanceof ICPPTemplateInstance );
assertSame( ((ICPPTemplateInstance)B2).getTemplateDefinition(), B );
ICPPTemplateParameter CR = (ICPPTemplateParameter) col.getName(12).resolveBinding();
assertSame( CR, T );
ICPPMethod f2 = (ICPPMethod) col.getName(13).resolveBinding();
assertSame( f2, f );
CR = (ICPPTemplateParameter) col.getName(14).resolveBinding();
assertSame( CR, T );
}
}

View file

@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IParameter;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
@ -66,7 +67,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
name = ns[ ns.length - 1 ];
}
IBinding binding = compTypeSpec.getName().resolveBinding();
IBinding binding = name.resolveBinding();
if( !(binding instanceof ICPPClassType ) )
return;
@ -100,6 +101,16 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
addBinding( m );
}
public IScope getParent() {
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
IASTName compName = compType.getName();
if( compName instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)compName).getNames();
compName = ns[ ns.length - 1 ];
}
return CPPVisitor.getContainingScope( compName );
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#addBinding(org.eclipse.cdt.core.dom.ast.IBinding)
*/
@ -172,7 +183,7 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
return CPPSemantics.resolveAmbiguities( name, getConstructors( resolve ) );
}
//9.2 ... The class-name is also inserted into the scope of the class itself
return compType.getName().resolveBinding();
return compName.resolveBinding();
}
return super.getBinding( name, resolve );
}
@ -195,7 +206,12 @@ public class CPPClassScope extends CPPScope implements ICPPClassScope {
public IBinding[] find(String name) throws DOMException {
char [] n = name.toCharArray();
ICPPASTCompositeTypeSpecifier compType = (ICPPASTCompositeTypeSpecifier) getPhysicalNode();
if( CharArrayUtils.equals( n, compType.getName().toCharArray() ) ){
IASTName compName = compType.getName();
if( compName instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)compName).getNames();
compName = ns[ ns.length - 1 ];
}
if( CharArrayUtils.equals( n, compName.toCharArray() ) ){
return (IBinding[]) ArrayUtil.addAll( IBinding.class, null, getConstructors( true ) );
}
return super.find( name );

View file

@ -169,9 +169,7 @@ public class CPPFunction implements ICPPFunction, ICPPInternalFunction {
IScope scope = getScope();
try {
IASTNode node = scope.getPhysicalNode();
while( !( node instanceof IASTTranslationUnit) )
node = node.getParent();
tu = (IASTTranslationUnit) node;
tu = node.getTranslationUnit();
} catch ( DOMException e ) {
}
}

View file

@ -83,7 +83,8 @@ public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope {
IASTFunctionDeclarator fdtor = (IASTFunctionDeclarator) getPhysicalNode();
IASTName name = fdtor.getName();
if( name instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)name).getNames();
ICPPASTQualifiedName qual = (ICPPASTQualifiedName) name;
IASTName [] ns = qual.getNames();
if( ns.length > 1){
IBinding binding = ns[ ns.length - 2 ].resolveBinding();
if( binding instanceof ICPPClassType )
@ -91,10 +92,12 @@ public class CPPFunctionScope extends CPPScope implements ICPPFunctionScope {
else if( binding instanceof ICPPNamespace )
return ((ICPPNamespace)binding).getNamespaceScope();
return binding.getScope();
} else if( qual.isFullyQualified() ){
return qual.getTranslationUnit().getScope();
}
}
return CPPVisitor.getContainingScope( fdtor );
return CPPVisitor.getContainingScope( name );
}

View file

@ -730,7 +730,13 @@ public class CPPSemantics {
IASTNode parent = name.getParent();
if( parent instanceof ICPPASTBaseSpecifier ) {
IASTNode n = CPPVisitor.getContainingBlockItem( parent );
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) parent.getParent();
IASTName n = compSpec.getName();
if( n instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
n = ns[ ns.length - 1 ];
}
return (ICPPScope) CPPVisitor.getContainingScope( n );
} else if( parent instanceof ICPPASTConstructorChainInitializer ){
ICPPASTConstructorChainInitializer initializer = (ICPPASTConstructorChainInitializer) parent;
@ -810,8 +816,6 @@ public class CPPSemantics {
while( scope != null ){
IASTNode blockItem = CPPVisitor.getContainingBlockItem( node );
if( blockItem != null && scope.getPhysicalNode() != blockItem.getParent() && !(scope instanceof ICPPNamespaceScope) )
blockItem = node;
ArrayWrapper directives = null;
if( !data.usingDirectivesOnly ){
@ -871,7 +875,7 @@ public class CPPSemantics {
return;
//if still not found, loop and check our containing scope
if( data.qualified() ) {
if( data.qualified() && !(scope instanceof ICPPTemplateScope) ) {
if( !data.usingDirectives.isEmpty() )
data.usingDirectivesOnly = true;
else
@ -880,7 +884,23 @@ public class CPPSemantics {
if( blockItem != null )
node = blockItem;
scope = (ICPPScope) scope.getParent();
ICPPScope parentScope = (ICPPScope) scope.getParent();
if( parentScope instanceof ICPPTemplateScope ){
IASTNode parent = node.getParent();
while( parent != null && !(parent instanceof ICPPASTTemplateDeclaration) ){
node = parent;
parent = parent.getParent();
}
if( parent != null ){
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) parent;
ICPPTemplateScope templateScope = templateDecl.getScope();
if( templateScope.getTemplateDefinition() == ((ICPPTemplateScope)parentScope).getTemplateDefinition() ){
parentScope = templateScope;
}
}
}
scope = parentScope;
}
}
@ -2837,14 +2857,13 @@ public class CPPSemantics {
}
public static boolean isSameFunction(IFunction function, IASTDeclarator declarator) {
IASTNode parent = declarator.getParent();
while( !(parent instanceof IASTDeclaration) ){
parent = parent.getParent();
}
IASTName name = declarator.getName();
ICPPASTTemplateDeclaration templateDecl = CPPTemplates.getTemplateDeclaration( name );
boolean fnIsTemplate = ( function instanceof ICPPFunctionTemplate );
boolean dtorIsTemplate = (parent.getPropertyInParent() == ICPPASTTemplateDeclaration.OWNED_DECLARATION );
boolean dtorIsTemplate = ( templateDecl != null );
if( fnIsTemplate && dtorIsTemplate ){
return CPPTemplates.isSameTemplate( (ICPPTemplateDefinition)function, declarator.getName() );
return CPPTemplates.isSameTemplate( (ICPPTemplateDefinition)function, name );
} else if( fnIsTemplate ^ dtorIsTemplate ){
return false;
}

View file

@ -164,6 +164,19 @@ public abstract class CPPTemplateDefinition implements ICPPTemplateDefinition, I
break;
}
if( definition != null || (declarations != null && declarations.length > 0 ) ){
IASTName templateName = ( definition != null ) ? definition : declarations[0];
ICPPASTTemplateDeclaration temp = CPPTemplates.getTemplateDeclaration( templateName );
ICPPASTTemplateParameter [] params = temp.getTemplateParameters();
if( params.length > i ) {
IASTName paramName = CPPTemplates.getTemplateParameterName( params[i] );
if( paramName.getBinding() != null ){
binding = paramName.getBinding();
name.setBinding( binding );
return binding;
}
}
}
//create a new binding and set it for the corresponding parameter in all known decls
if( templateParameter instanceof ICPPASTSimpleTypeTemplateParameter )
binding = new CPPTemplateTypeParameter( name );
@ -211,7 +224,7 @@ public abstract class CPPTemplateDefinition implements ICPPTemplateDefinition, I
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/
public IScope getScope() {
return CPPVisitor.getContainingScope( getTemplateName().getParent() );
return CPPVisitor.getContainingScope( getTemplateName() );
}
/* (non-Javadoc)

View file

@ -13,8 +13,17 @@
*/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
@ -53,4 +62,40 @@ public class CPPTemplateScope extends CPPScope implements ICPPTemplateScope {
return null;
}
public IScope getParent() {
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) getPhysicalNode();
IASTName name = CPPTemplates.getTemplateName( templateDecl );
IASTNode p = name.getParent();
if( p instanceof ICPPASTQualifiedName ){
ICPPASTQualifiedName qual = (ICPPASTQualifiedName) p;
IASTName [] names = qual.getNames();
int i = 0;
for( ; i < names.length; i++ ){
if( names[i] == name ) break;
}
if( i > 0 ){
try {
IBinding binding = names[i - 1].resolveBinding();
if( binding instanceof ICPPClassType ){
return ((ICPPClassType)binding).getCompositeScope();
} else if( binding instanceof ICPPNamespace ){
return ((ICPPNamespace)binding).getNamespaceScope();
} else if( binding instanceof ICPPInternalUnknown ){
return ((ICPPInternalUnknown)binding).getUnknownScope();
} else if( binding instanceof IProblemBinding ){
if( binding instanceof ICPPScope )
return (IScope) binding;
return new CPPScope.CPPScopeProblem( names[i-1], IProblemBinding.SEMANTIC_BAD_SCOPE, names[i-1].toCharArray() );
}
} catch( DOMException e ){
return e.getProblem();
}
} else if( qual.isFullyQualified() ){
return qual.getTranslationUnit().getScope();
}
}
while( templateDecl.getParent() instanceof ICPPASTTemplateDeclaration )
templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getParent();
return CPPVisitor.getContainingScope( templateDecl );
}
}

View file

@ -53,6 +53,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
@ -68,7 +69,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTypeParameter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
@ -98,6 +98,13 @@ public class CPPTemplates {
IASTNode parent = param.getParent();
IBinding binding = null;
if( parent instanceof ICPPASTTemplateDeclaration ){
// IASTName name = getTemplateName( (ICPPASTTemplateDeclaration) parent );
// if( name != null ){
// if( name instanceof ICPPASTTemplateId && !(name.getParent() instanceof ICPPASTQualifiedName) )
// name = ((ICPPASTTemplateId)name).getTemplateName();
//
// binding = name.resolveBinding();
// }
ICPPASTTemplateDeclaration [] templates = new ICPPASTTemplateDeclaration [] { (ICPPASTTemplateDeclaration) parent };
while( parent.getParent() instanceof ICPPASTTemplateDeclaration ){
@ -315,7 +322,7 @@ public class CPPTemplates {
CPPSemantics.LookupData data = new CPPSemantics.LookupData( name );
data.forceQualified = true;
IScope scope = CPPVisitor.getContainingScope( name );
if( scope instanceof ICPPTemplateScope && name.getPropertyInParent() != ICPPASTQualifiedName.SEGMENT_NAME ){
if( scope instanceof ICPPTemplateScope ){
try {
scope = scope.getParent();
} catch (DOMException e) {
@ -501,14 +508,6 @@ public class CPPTemplates {
return null;
}
/**
* @param scope
* @return
*/
public static ICPPTemplateDefinition getTemplateDefinition(ICPPTemplateScope scope) {
if( scope != null ) {}
return null;
}
/**
* @param decl
@ -608,55 +607,109 @@ public class CPPTemplates {
public static ICPPASTTemplateDeclaration getTemplateDeclaration( IASTName name ){
if( name == null ) return null;
// if( name.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_NAME )
// name = (IASTName) name.getParent();
//
// if( !(name instanceof ICPPASTTemplateId) )
// return null;
IASTNode parent = name.getParent();
while( parent != null && !(parent instanceof ICPPASTTemplateDeclaration) &&
!(parent instanceof ICPPASTTemplatedTypeTemplateParameter) )
{
while( parent instanceof IASTName ){
parent = parent.getParent();
}
if( parent == null ) return null;
if( parent instanceof IASTDeclSpecifier ){
parent = parent.getParent();
} else {
while( parent instanceof IASTDeclarator ){
parent = parent.getParent();
}
}
if( parent instanceof IASTDeclaration && parent.getParent() instanceof ICPPASTTemplateDeclaration ){
parent = parent.getParent();
} else {
return null;
}
if( parent instanceof ICPPASTTemplateDeclaration ){
ICPPASTTemplateDeclaration [] templates = new ICPPASTTemplateDeclaration [] { (ICPPASTTemplateDeclaration) parent };
ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) parent;
while( templateDecl.getParent() instanceof ICPPASTTemplateDeclaration )
templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getParent();
while( parent.getParent() instanceof ICPPASTTemplateDeclaration ){
parent = parent.getParent();
templates = (ICPPASTTemplateDeclaration[]) ArrayUtil.append( ICPPASTTemplateDeclaration.class, templates, parent );
IASTName [] ns = null;
if( name instanceof ICPPASTQualifiedName ){
ns = ((ICPPASTQualifiedName)name).getNames();
name = ns[ ns.length - 1 ];
} else if( name.getParent() instanceof ICPPASTQualifiedName ){
ns = ((ICPPASTQualifiedName)name.getParent()).getNames();
}
templates = (ICPPASTTemplateDeclaration[]) ArrayUtil.trim( ICPPASTTemplateDeclaration.class, templates );
if( name == null )
if( ns != null ){
IASTDeclaration currDecl = templateDecl;
for (int j = 0; j < ns.length; j++) {
if( ns[j] == name ){
if( ns[j] instanceof ICPPASTTemplateId || j + 1 == ns.length ){
if( currDecl instanceof ICPPASTTemplateDeclaration )
return (ICPPASTTemplateDeclaration) currDecl;
return null;
}
}
if( ns[j] instanceof ICPPASTTemplateId ){
if( currDecl instanceof ICPPASTTemplateDeclaration )
currDecl = ((ICPPASTTemplateDeclaration) currDecl).getDeclaration();
else
return null; //??? this would imply bad ast or code
}
}
} else {
return templateDecl;
}
}
return null;
}
if( name.getParent() instanceof ICPPASTQualifiedName ){
int idx = templates.length;
int i = -1;
IASTName [] ns = ((ICPPASTQualifiedName) name.getParent()).getNames();
public static IASTName getTemplateName( ICPPASTTemplateDeclaration templateDecl ){
if( templateDecl == null ) return null;
ICPPASTTemplateDeclaration decl = templateDecl;
while( decl.getParent() instanceof ICPPASTTemplateDeclaration )
decl = (ICPPASTTemplateDeclaration) decl.getParent();
IASTDeclaration nestedDecl = templateDecl.getDeclaration();
while( nestedDecl instanceof ICPPASTTemplateDeclaration ){
nestedDecl = ((ICPPASTTemplateDeclaration)nestedDecl).getDeclaration();
}
IASTName name = null;
if( nestedDecl instanceof IASTSimpleDeclaration ){
IASTSimpleDeclaration simple = (IASTSimpleDeclaration) nestedDecl;
if( simple.getDeclarators().length == 1 ){
IASTDeclarator dtor = simple.getDeclarators()[0];
while( dtor.getNestedDeclarator() != null )
dtor = dtor.getNestedDeclarator();
name = dtor.getName();
} else if( simple.getDeclarators().length == 0 ){
IASTDeclSpecifier spec = simple.getDeclSpecifier();
if( spec instanceof ICPPASTCompositeTypeSpecifier )
name = ((ICPPASTCompositeTypeSpecifier)spec).getName();
else if( spec instanceof ICPPASTElaboratedTypeSpecifier )
name = ((ICPPASTElaboratedTypeSpecifier)spec).getName();
}
} else if( nestedDecl instanceof IASTFunctionDefinition ){
name = ((IASTFunctionDefinition)nestedDecl).getDeclarator().getName();
}
if( name != null ){
if( name instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName) name).getNames();
IASTDeclaration currDecl = decl;
for (int j = 0; j < ns.length; j++) {
if( ns[j] instanceof ICPPASTTemplateId || j + 1 == ns.length){
++i;
}
if( ns[j] == name ){
if( i < idx )
return templates[ i ];
if( currDecl == templateDecl )
return ns[j];
if( currDecl instanceof ICPPASTTemplateDeclaration )
currDecl = ((ICPPASTTemplateDeclaration)currDecl).getDeclaration();
else
return null;
}
}
} else {
return templates[0];
return name;
}
}
} else if( parent instanceof ICPPASTTemplatedTypeTemplateParameter ){
}
return null;
}
private static class ClearBindingAction extends CPPASTVisitor {
@ -692,6 +745,9 @@ public class CPPTemplates {
return false;
}
ICPPASTTemplateDeclaration templateDecl = getTemplateDeclaration( name );
if( templateDecl == null )
return false;
ICPPASTTemplateParameter [] templateParams = templateDecl.getTemplateParameters();
if( defParams.length != templateParams.length )
return false;
@ -718,7 +774,7 @@ public class CPPTemplates {
int i = 0;
for(; i < ps.length; i++) {
IType t1 = CPPVisitor.createType( params[i].getDeclarator() );
IType t2 = ps[0].getType();
IType t2 = ps[i].getType();
if( ! t1.isSameType( t2 ) ){
break;
}

View file

@ -450,7 +450,7 @@ public class CPPVisitor {
}
boolean template = false;
ICPPScope scope = (ICPPScope) getContainingScope( name );
ICPPScope scope = (ICPPScope) getContainingScope( (IASTNode) name );
if( scope instanceof ICPPTemplateScope ){
ICPPScope parentScope = null;
try {
@ -598,7 +598,12 @@ public class CPPVisitor {
} catch ( DOMException e ) {
return false;
}
return isConstructor( clsTypeSpec.getName(), declarator );
IASTName clsName = clsTypeSpec.getName();
if( clsName instanceof ICPPASTQualifiedName ){
IASTName [] names = ((ICPPASTQualifiedName)clsName).getNames();
clsName = names[ names.length - 1 ];
}
return isConstructor( clsName, declarator );
}
public static boolean isConstructor( IASTName parentName, IASTDeclarator declarator ){
if( declarator == null || !(declarator instanceof IASTFunctionDeclarator) )
@ -631,9 +636,10 @@ public class CPPVisitor {
if( node == null )
return null;
while( node != null ){
if( node instanceof IASTName ){
if( node instanceof IASTName && !( node instanceof ICPPASTQualifiedName ) ){
return getContainingScope( (IASTName) node );
} else if( node instanceof IASTDeclaration ){
}
if( node instanceof IASTDeclaration ){
IASTNode parent = node.getParent();
if( parent instanceof IASTTranslationUnit ){
return ((IASTTranslationUnit)parent).getScope();
@ -645,15 +651,19 @@ public class CPPVisitor {
return ((IASTCompositeTypeSpecifier)parent).getScope();
} else if( parent instanceof ICPPASTNamespaceDefinition ) {
return ((ICPPASTNamespaceDefinition)parent).getScope();
} else if( parent instanceof ICPPASTTemplateDeclaration ){
return ((ICPPASTTemplateDeclaration)parent).getScope();
}
} else if( node instanceof IASTStatement ){
return getContainingScope( (IASTStatement) node );
} else if( node instanceof IASTTypeId ){
if( node.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT ){
ICPPASTTemplateDeclaration decl = CPPTemplates.getTemplateDeclaration( (IASTName) node.getParent() );
if( decl == null ){
node = node.getParent();
if( node instanceof ICPPASTTemplateParameter )
return CPPTemplates.getContainingScope( node );
while( node instanceof IASTName )
node = node.getParent();
continue;
}
}
} else if( node instanceof IASTParameterDeclaration ){
IASTNode parent = node.getParent();
if( parent instanceof ICPPASTFunctionDeclarator ){
@ -691,6 +701,15 @@ public class CPPVisitor {
}
} else if( node instanceof ICPPASTTemplateParameter ){
return CPPTemplates.getContainingScope( node );
} else if( node instanceof ICPPASTBaseSpecifier ) {
ICPPASTCompositeTypeSpecifier compSpec = (ICPPASTCompositeTypeSpecifier) node.getParent();
IASTName n = compSpec.getName();
if( n instanceof ICPPASTQualifiedName ){
IASTName [] ns = ((ICPPASTQualifiedName)n).getNames();
n = ns[ ns.length - 1 ];
}
return (ICPPScope) CPPVisitor.getContainingScope( n );
}
node = node.getParent();
}
@ -700,6 +719,14 @@ public class CPPVisitor {
public static IScope getContainingScope( IASTName name ){
IASTNode parent = name.getParent();
try {
if( parent instanceof ICPPASTTemplateId ){
name = (IASTName) parent;
parent = name.getParent();
}
ICPPASTTemplateDeclaration decl = CPPTemplates.getTemplateDeclaration( name );
if( decl != null )
return decl.getScope();
if( parent instanceof ICPPASTQualifiedName ){
IASTName [] names = ((ICPPASTQualifiedName) parent).getNames();
int i = 0;