From ce4decd0a0ca351fff8195ec87d452b03e244b2f Mon Sep 17 00:00:00 2001
From: Andrew Niefer <aniefer@ca.ibm.com>
Date: Mon, 9 May 2005 16:15:14 +0000
Subject: [PATCH] Fix template scoping - helps with nested templates & template
 specializations - fxes bug 90686

---
 .../tests/ast2/AST2CPPSpecFailingTest.java    |  80 ------
 .../parser/tests/ast2/AST2CPPSpecTest.java    |  73 ++++++
 .../parser/tests/ast2/AST2TemplateTests.java  | 238 ++++++++++++++++++
 .../core/dom/parser/cpp/CPPClassScope.java    |  22 +-
 .../core/dom/parser/cpp/CPPFunction.java      |   4 +-
 .../core/dom/parser/cpp/CPPFunctionScope.java |   7 +-
 .../core/dom/parser/cpp/CPPSemantics.java     |  41 ++-
 .../dom/parser/cpp/CPPTemplateDefinition.java |  15 +-
 .../core/dom/parser/cpp/CPPTemplateScope.java |  45 ++++
 .../core/dom/parser/cpp/CPPTemplates.java     | 148 +++++++----
 .../core/dom/parser/cpp/CPPVisitor.java       |  45 +++-
 11 files changed, 563 insertions(+), 155 deletions(-)

diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java
index c14c1323c75..cf89a300259 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java
@@ -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*);
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java
index 58f7364173d..fb9de73c259 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java
@@ -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 {
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
index 739ae6dda8e..10a43745e55 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java
@@ -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 );
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
index ec679d65ddf..05d9e2fd39a 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassScope.java
@@ -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 );
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
index c874db271fe..fa722ae998e 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunction.java
@@ -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 ) {
                 }
 	        }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java
index 0d71c875056..f0edced4fc4 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionScope.java
@@ -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 );
 	}
 
 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java
index 60ee157019f..229c95aa11d 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java
@@ -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;
 		} 
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java
index 7f4c73d16bf..173173468d8 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateDefinition.java
@@ -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)
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateScope.java
index 31a82407d29..1222fb9f47f 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateScope.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateScope.java
@@ -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 );
+	}
 }
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java
index dc17d7b6e35..4ca76f2da87 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplates.java
@@ -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) )
-		{
-			parent = parent.getParent();
+		while( parent instanceof IASTName ){
+		    parent = parent.getParent();
+		}
+		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 == null ) return null;
-		
 		if( parent instanceof ICPPASTTemplateDeclaration ){
-			ICPPASTTemplateDeclaration [] templates = new ICPPASTTemplateDeclaration [] { (ICPPASTTemplateDeclaration) parent };
-			
-			while( parent.getParent() instanceof ICPPASTTemplateDeclaration ){
-				parent = parent.getParent();
-				templates = (ICPPASTTemplateDeclaration[]) ArrayUtil.append( ICPPASTTemplateDeclaration.class, templates, parent );
+		    ICPPASTTemplateDeclaration templateDecl = (ICPPASTTemplateDeclaration) parent;
+		    while( templateDecl.getParent() instanceof ICPPASTTemplateDeclaration )
+		        templateDecl = (ICPPASTTemplateDeclaration) templateDecl.getParent();
+
+			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 )
-				return null;
-				
-			if( name.getParent() instanceof ICPPASTQualifiedName ){
-				int idx = templates.length;
-				int i = -1;
-				IASTName [] ns = ((ICPPASTQualifiedName) name.getParent()).getNames();
+			if( ns != null ){
+				IASTDeclaration currDecl = templateDecl;
 				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 ];
-						return null;
+						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 templates[0];
+				return templateDecl;
 			}
-		} else if( parent instanceof ICPPASTTemplatedTypeTemplateParameter ){
-			
 		}
 		return  null;
+	}
+	
+	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){
+						if( currDecl == templateDecl )
+							return ns[j];
+						if( currDecl instanceof ICPPASTTemplateDeclaration )
+							currDecl = ((ICPPASTTemplateDeclaration)currDecl).getDeclaration();
+						else
+							return null;
+					}
+				}
+		    } else {
+		        return name;
+		    }
+		}
+
+		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;
 						}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java
index 35326432ece..fb009629632 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java
@@ -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 ){
-				node = node.getParent();
-				if( node instanceof ICPPASTTemplateParameter )
-				    return CPPTemplates.getContainingScope( node );
+				if( node.getPropertyInParent() == ICPPASTTemplateId.TEMPLATE_ID_ARGUMENT ){
+				    ICPPASTTemplateDeclaration decl = CPPTemplates.getTemplateDeclaration( (IASTName) node.getParent() );
+			        if( decl == null ){
+			            node = node.getParent();
+			            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;