From bb5e431bf187a9f3cabb72045694fbaea414a702 Mon Sep 17 00:00:00 2001
From: Argyrios Kyrtzidis <akyrtzi@gmail.com>
Date: Thu, 4 Nov 2010 03:18:57 +0000
Subject: [PATCH] Don't instantiate members not belonging in the semantic
 context of the template. e.g. for:

    template <int i> class A {
      class B *g;
    };

'class B' has the template as lexical context but semantically it is
introduced in namespace scope.

Fixes rdar://8611125 & http://llvm.org/PR8505

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@118235 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Sema/SemaTemplateInstantiate.cpp       | 12 ++++++++++++
 test/CodeGenCXX/template-instantiation.cpp | 13 +++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 71235d9285..f78fe81aa8 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1223,6 +1223,18 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
   for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
          MemberEnd = Pattern->decls_end();
        Member != MemberEnd; ++Member) {
+    // Don't instantiate members not belonging in this semantic context.
+    // e.g. for:
+    // @code
+    //    template <int i> class A {
+    //      class B *g;
+    //    };
+    // @endcode
+    // 'class B' has the template as lexical context but semantically it is
+    // introduced in namespace scope.
+    if ((*Member)->getDeclContext() != Pattern)
+      continue;
+
     Decl *NewMember = SubstDecl(*Member, Instantiation, TemplateArgs);
     if (NewMember) {
       if (FieldDecl *Field = dyn_cast<FieldDecl>(NewMember))
diff --git a/test/CodeGenCXX/template-instantiation.cpp b/test/CodeGenCXX/template-instantiation.cpp
index a8729035e2..0df2e23c70 100644
--- a/test/CodeGenCXX/template-instantiation.cpp
+++ b/test/CodeGenCXX/template-instantiation.cpp
@@ -109,3 +109,16 @@ namespace test4 {
     A<int>::foo();
   }
 }
+
+namespace PR8505 {
+// Hits an assertion due to bogus instantiation of class B.
+template <int i> class A {
+  class B* g;
+};
+class B {
+  void f () {}
+};
+// Should not instantiate class B since it is introduced in namespace scope.
+// CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv
+template class A<0>;
+}
-- 
2.40.0